diff --git a/mkdocs-website/docs/en/changelog.md b/mkdocs-website/docs/en/changelog.md index a650534fcba..c91b1d0f6ba 100644 --- a/mkdocs-website/docs/en/changelog.md +++ b/mkdocs-website/docs/en/changelog.md @@ -27,6 +27,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 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) ### Changed - Asset embed to include `all:frontend/dist` to support frameworks that generate subfolders by @atterpac in [#3887](https://github.com/wailsapp/wails/pull/3887) diff --git a/mkdocs-website/docs/en/learn/bindings.md b/mkdocs-website/docs/en/learn/bindings.md index 82f32a026cf..2d680f5d01b 100644 --- a/mkdocs-website/docs/en/learn/bindings.md +++ b/mkdocs-website/docs/en/learn/bindings.md @@ -329,3 +329,50 @@ export class Person { ``` Using TypeScript bindings provides type safety and improved IDE support when working with the generated code in your frontend. + +### Using `context.Context` + +When defining service methods in Go, you can include `context.Context` as the first parameter. The runtime will automatically provide a context when the method is called from the frontend. + +The context provides several powerful features: + +1. **Cancellation Support**: Long-running operations can be cancelled from the frontend, which will raise an error through the Promise chain. + +2. **Window Information**: You can determine which window made the call using these context keys: + - `application.WindowNameKey` - Returns the name of the calling window + - `application.WindowIDKey` - Returns the ID of the calling window + +Here are some examples: + +```go +// Basic context usage with cancellation +func (s *MyService) LongRunningTask(ctx context.Context, input string) (string, error) { + select { + // Check if the context has been cancelled from the frontend + case <-ctx.Done(): + return "", ctx.Err() + default: + // Process task + return "completed", nil + } +} + +// Getting caller window information +func (s *MyService) WindowAwareMethod(ctx context.Context) (string, error) { + windowName := ctx.Value(application.WindowNameKey).(string) + windowID := ctx.Value(application.WindowIDKey).(string) + return fmt.Sprintf("Called from window: %s (ID: %s)", windowName, windowID), nil +} +``` + +From the frontend, these methods can be called normally. If you need to cancel a long-running operation, the Promise will be rejected with the cancellation error: + +```javascript +// Call the method +const promise = MyService.LongRunningTask("input"); + +// Cancel it later if needed +// This will cause the context to be cancelled in the Go method +promise.cancel(); +``` + diff --git a/v3/examples/build/Taskfile.yml b/v3/examples/build/Taskfile.yml index 332eb608663..f4e5e1f151f 100644 --- a/v3/examples/build/Taskfile.yml +++ b/v3/examples/build/Taskfile.yml @@ -78,7 +78,7 @@ tasks: platforms: - windows cmds: - - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails_windows.syso vars: GOARCH: '{{.GOARCH}}' @@ -93,7 +93,7 @@ tasks: vars: GOARCH: amd64 - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/{{.APP_NAME}} - - powershell Remove-item wails.syso + - powershell Remove-item *.syso package:windows:arm64: @@ -105,6 +105,6 @@ tasks: vars: GOARCH: arm64 - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/buildtest.arm64.exe - - powershell Remove-item wails.syso + - powershell Remove-item *.syso env: GOARCH: arm64 diff --git a/v3/examples/dev/Taskfile.yml b/v3/examples/dev/Taskfile.yml index 9886a67cc1d..8d2d4671647 100644 --- a/v3/examples/dev/Taskfile.yml +++ b/v3/examples/dev/Taskfile.yml @@ -166,7 +166,7 @@ tasks: dir: build platform: windows cmds: - - wails generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json vars: ARCH: $GOARCH @@ -180,4 +180,4 @@ tasks: vars: ARCH: amd64 - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/{{.APP_NAME}}.exe - - powershell Remove-item wails.syso + - powershell Remove-item *.syso diff --git a/v3/examples/dialogs/Taskfile.yml b/v3/examples/dialogs/Taskfile.yml index 51fbd49ac73..90ac01145bd 100644 --- a/v3/examples/dialogs/Taskfile.yml +++ b/v3/examples/dialogs/Taskfile.yml @@ -75,7 +75,7 @@ tasks: platforms: - windows cmds: - - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json vars: GOARCH: '{{.GOARCH}}' @@ -90,7 +90,7 @@ tasks: vars: GOARCH: amd64 - go build -tags production -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - powershell Remove-item wails.syso + - powershell Remove-item *.syso package:windows:arm64: @@ -102,6 +102,6 @@ tasks: vars: GOARCH: arm64 - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/buildtest.arm64.exe - - powershell Remove-item wails.syso + - powershell Remove-item *.syso env: GOARCH: arm64 diff --git a/v3/examples/file-association/build/Taskfile.windows.yml b/v3/examples/file-association/build/Taskfile.windows.yml index f815bd0ae5c..f141fcd2f50 100644 --- a/v3/examples/file-association/build/Taskfile.windows.yml +++ b/v3/examples/file-association/build/Taskfile.windows.yml @@ -13,6 +13,7 @@ tasks: - 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: @@ -30,7 +31,7 @@ tasks: summary: Generates Windows `.syso` file dir: build cmds: - - wails3 generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails3 generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json vars: ARCH: '{{.ARCH | default ARCH}}' diff --git a/v3/internal/commands/build_assets/Taskfile.windows.yml b/v3/internal/commands/build_assets/Taskfile.windows.yml index f815bd0ae5c..c893f1cc148 100644 --- a/v3/internal/commands/build_assets/Taskfile.windows.yml +++ b/v3/internal/commands/build_assets/Taskfile.windows.yml @@ -13,6 +13,7 @@ tasks: - 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: @@ -30,7 +31,7 @@ tasks: summary: Generates Windows `.syso` file dir: build cmds: - - wails3 generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails3 generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails_windows_{{.ARCH}}.syso vars: ARCH: '{{.ARCH | default ARCH}}' diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package.json b/v3/internal/runtime/desktop/@wailsio/runtime/package.json index dea509f7de7..1014fc1c974 100644 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package.json +++ b/v3/internal/runtime/desktop/@wailsio/runtime/package.json @@ -3,6 +3,7 @@ "type": "module", "version": "3.0.0-alpha.29", "description": "Wails Runtime", + "types": "types/index.d.ts", "exports": { ".": { "types": "./types/index.d.ts", diff --git a/v3/internal/templates/_base/default/Taskfile.tmpl.yml b/v3/internal/templates/_base/default/Taskfile.tmpl.yml index 924d3159895..9b89ad87dd5 100644 --- a/v3/internal/templates/_base/default/Taskfile.tmpl.yml +++ b/v3/internal/templates/_base/default/Taskfile.tmpl.yml @@ -172,7 +172,7 @@ tasks: dir: build platform: windows cmds: - - wails generate syso -arch {{ "{{.ARCH}}" }} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails.syso + - wails generate syso -arch {{ "{{.ARCH}}" }} -icon icon.ico -manifest wails.exe.manifest -info info.json vars: ARCH: $GOARCH @@ -186,4 +186,4 @@ tasks: vars: ARCH: amd64 - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/{{ "{{.APP_NAME}}" }}.exe - - powershell Remove-item wails.syso + - powershell Remove-item *.syso diff --git a/v3/pkg/application/messageprocessor_call.go b/v3/pkg/application/messageprocessor_call.go index 714d766db7c..45a6fba0cad 100644 --- a/v3/pkg/application/messageprocessor_call.go +++ b/v3/pkg/application/messageprocessor_call.go @@ -7,8 +7,12 @@ import ( "net/http" ) +type contextKey string + const ( - CallBinding = 0 + CallBinding = 0 + WindowNameKey contextKey = "WindowName" + WindowIDKey contextKey = "WindowID" ) func (m *MessageProcessor) callErrorCallback(window Window, message string, callID *string, err error) { @@ -95,6 +99,12 @@ func (m *MessageProcessor) processCallMethod(method int, rw http.ResponseWriter, return } + // Set the context values for the window + if window != nil { + ctx = context.WithValue(ctx, WindowNameKey, window.Name()) + ctx = context.WithValue(ctx, WindowIDKey, window.ID()) + } + go func() { defer func() { cancel() @@ -123,7 +133,11 @@ func (m *MessageProcessor) processCallMethod(method int, rw http.ResponseWriter, var jsonArgs struct { Args json.RawMessage `json:"args"` } - params.ToStruct(&jsonArgs) + err = params.ToStruct(&jsonArgs) + if err != nil { + m.callErrorCallback(window, "Error parsing arguments: %s", callID, err) + return + } m.Info("Call Binding:", "method", boundMethod, "args", string(jsonArgs.Args), "result", result) }() m.ok(rw)