-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V3 alpha feature/file association port #3873
Conversation
Support `ApplicationOpenedWithFile` event on Windows Add docs
Support `ApplicationOpenedWithFile` event on Windows Add docs Add test project
Fix show window bug.
WalkthroughThe pull request introduces several enhancements to the Wails framework, primarily focusing on file association features. Key changes include the addition of documentation on handling file associations, updates to event types for file opening, and modifications to application behavior on macOS. New configuration files and tasks for building applications are included, alongside updates to existing application structures to support these features. Overall, the changes aim to facilitate file management and improve user interaction within the Wails applications. Changes
Assessment against linked issues
Possibly related PRs
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Deploying wails with Cloudflare Pages
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 32
🧹 Outside diff range and nitpick comments (63)
v3/examples/file-association/greetservice.go (1)
1-7
: LGTM, but example seems incomplete for file association demonstration.While the code is syntactically correct, this example appears to be missing the actual file association demonstration that this PR aims to port from v2 to v3. Consider enhancing this example to show:
- How to register file associations
- How to handle file open events
- How to process associated files when the application starts
Would you like assistance in expanding this example to better demonstrate the file association feature?
v3/pkg/application/application_darwin_delegate.h (1)
14-14
: Consider adding safety measures for HandleOpenFile.The C-style string parameter requires careful memory management. Consider these improvements:
- Add nullability annotations for better Swift interop
- Document the ownership/lifecycle of the char* parameter
-extern void HandleOpenFile(char *); +extern void HandleOpenFile(char * _Nonnull filename) NS_SWIFT_NAME(handleOpenFile(_:));v3/examples/file-association/README.md (2)
4-4
: Format the URL using proper markdown link syntax.Convert the bare URL to a properly formatted markdown link for better readability and maintainability.
-More info at: https://v3alpha.wails.io/learn/guides/file-associations/ +More info at: [File Associations Guide](https://v3alpha.wails.io/learn/guides/file-associations/)🧰 Tools
🪛 Markdownlint
4-4: null
Bare URL used(MD034, no-bare-urls)
6-11
: Enhance instructions with additional details and verification steps.While the instructions are clear, consider adding the following details to improve user experience:
- Specify where to find or how to create the
test.wails
file- Explain what the
.wails
extension represents- Add verification steps to confirm successful file association
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. Create a test file with the `.wails` extension (e.g., `echo "test" > test.wails`) -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. +4. Double-click on the `test.wails` file: + - On Windows: The file should automatically open with your application + - On macOS: Select the built application when prompted +5. Verify that: + - The application launches successfully + - The file content is properly handled by the applicationv3/examples/file-association/frontend/main.js (2)
7-17
: Improve error handling and avoid global functionsConsider these improvements:
- Avoid attaching to window object directly
- Add proper input sanitization
- Provide more informative error messages
-window.doGreet = () => { +const doGreet = () => { let name = document.getElementById('name').value; - if (!name) { + if (!name || !name.trim()) { name = 'anonymous'; } + name = name.trim(); GreetService.Greet(name).then((result) => { resultElement.innerText = result; }).catch((err) => { - console.log(err); + console.error('Greeting failed:', err); + resultElement.innerText = 'Error: Failed to generate greeting'; }); } + +// Export if needed +window.doGreet = doGreet;
1-21
: Enhance example to demonstrate file association featuresAs this is part of the file association example directory, it should primarily demonstrate how to handle file associations in a Wails application. The current implementation focuses on greeting functionality instead. Consider restructuring this example to:
- Focus on file handling and association features
- Demonstrate proper event handling for file open events
- Show how to process different file types
- Include error handling specific to file operations
Would you like assistance in implementing a more focused file association example?
v3/examples/file-association/build/devmode.config.yaml (1)
1-4
: Consider adjusting development mode settings for better developer experience.The current configuration might hinder development productivity:
- Log level
warn
may hide useful debugging information- 1000ms debounce could cause noticeable delays in development feedback
Consider this configuration for development:
config: root_path: . - log_level: warn - debounce: 1000 + log_level: debug + debounce: 500v3/examples/file-association/Taskfile.yml (1)
9-12
: LGTM! Consider adding variable descriptions.The variables are well-defined with appropriate defaults. Consider adding comments to document the purpose of each variable, especially
VITE_PORT
.vars: + # Name of the application binary APP_NAME: "fileassoc" + # Directory where built binaries are stored BIN_DIR: "bin" + # Port for Vite development server, defaults to 9245 if WAILS_VITE_PORT is not set VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}'v3/examples/file-association/build/appimage/build.sh (2)
1-6
: Consider removing the -x flag in production.While the strict error handling is excellent, the -x flag (which prints each command) might generate too much output in production. Consider keeping it only for debugging.
-set -euxo pipefail +set -euo pipefail
1-26
: Consider adding logging and documentation.As this is an example script that others will reference, consider these architectural improvements:
- Add a logging function to standardize output messages
- Include usage documentation in script comments
- Consider supporting command-line arguments for overriding environment variables
- Add a cleanup function to handle intermediate files and failed states
Would you like me to provide an example implementation of these improvements?
v3/internal/commands/updatable_build_assets/Info.dev.plist.tmpl (1)
Add file association configuration to the plist template
The v2 template includes file association support through
CFBundleDocumentTypes
, but this configuration is missing in the v3 template. Add the following configuration block tov3/internal/commands/updatable_build_assets/Info.dev.plist.tmpl
:{{if .FileAssociations}} <key>CFBundleDocumentTypes</key> <array> {{range .FileAssociations}} <dict> <key>CFBundleTypeExtensions</key> <array> <string>{{.Ext}}</string> </array> <key>CFBundleTypeName</key> <string>{{.Name}}</string> <key>CFBundleTypeRole</key> <string>{{.Role}}</string> <key>CFBundleTypeIconFile</key> <string>{{.IconName}}</string> </dict> {{end}} </array> {{end}}🔗 Analysis chain
Line range hint
1-32
: Verify file association configuration in plist template.Since this PR implements file association support, the template might need additional keys like
CFBundleDocumentTypes
for file type associations.Let's check if other plist templates in the codebase include file association configurations:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for file association configurations in plist templates # and ensure consistency across templates # Search for file association related keys in plist templates rg -A 5 'CFBundleDocumentTypes|UTExportedTypeDeclarations|LSItemContentTypes' --glob '*.plist*'Length of output: 1278
Script:
#!/bin/bash # Let's check the v2 plist templates to understand the file association structure cat v2/pkg/buildassets/build/darwin/Info.plistLength of output: 2216
v3/internal/commands/build_assets/config.yml (4)
8-14
: Add validation guidelines for info fields.Consider adding comments about:
- Required format for
productIdentifier
(reverse domain notation)- Version format requirements (semver recommended)
- Character limits or restrictions for fields
18-29
: Enhance file associations documentation.Please add comments to clarify:
- Valid values for the
role
field (e.g., Editor, Viewer, Shell)- Icon requirements (format, size, location)
- Whether these examples should be uncommented for basic setup
Consider adding this documentation above the section:
# File Associations +# Valid roles: Editor, Viewer, Shell +# Icons should be provided in .ico format for Windows and .icns for macOS +# Place icons in the build/appicon directory +# Uncomment and modify the examples below to add file associations
30-32
: Document the structure of 'other' data.The purpose and expected structure of the
other
section is unclear. Please add documentation about:
- Required fields for each entry
- Purpose of this section
- How this data is used in the application
🧰 Tools
🪛 yamllint
[error] 32-32: no new line character at the end of file
(new-line-at-end-of-file)
7-14
: Consider security implications of configuration.The
info
section contains potentially sensitive company information. Consider:
- Adding documentation about using environment variables for sensitive values
- Providing guidance on configuration file management in version control
- Adding validation for the
productIdentifier
to prevent spoofingmkdocs-website/docs/en/status.md (1)
23-26
: Consider adding more details about the in-progress features.While the status items clearly indicate what's being worked on, it would be helpful to provide more context about:
- The scope of file association support (e.g., which platforms are supported)
- The relationship between file associations and drag-and-drop support
- Expected completion timeline or milestones
Consider expanding the section like this:
## Alpha 8 Status -In Progress: Add support for File Associations -In Progress: Drag and Drop support for Linux +In Progress: +- File Associations + - Porting from v2 (see #3655) + - Supporting Windows and macOS platforms + - Expected in next alpha release + +- Drag and Drop support for Linux + - Complementing existing platform support + - Enhancing file handling capabilitiesv3/examples/file-association/build/Taskfile.darwin.yml (1)
43-45
: Add validation to the run task.The run task should verify that the binary exists before attempting to execute it.
Consider adding validation:
run: + preconditions: + - sh: test -f {{.BIN_DIR}}/{{.APP_NAME}} + msg: "Binary not found. Please run the build task first." cmds: - '{{.BIN_DIR}}/{{.APP_NAME}}'v3/pkg/application/context_application_event.go (2)
7-7
: Consider a more specific constant name.The constant
filename
could be more descriptive to indicate its specific purpose in the context of file association events. Consider using something likeopenedWithFilename
orassociatedFilename
to better reflect its usage.- filename = "filename" + openedWithFilename = "openedWithFilename"
63-73
: Add documentation and consider storing constant lookup result.
- Add documentation for this exported method to describe its purpose and return value.
- Consider storing the constant lookup result to avoid potential maintenance issues if the constant name changes.
+// Filename returns the filepath that was used to open the application. +// Returns an empty string if no file was used or if the value is invalid. func (c ApplicationEventContext) Filename() string { - filename, ok := c.data[filename] + value, ok := c.data[filename] if !ok { return "" } - result, ok := filename.(string) + result, ok := value.(string) if !ok { return "" } return result }v3/examples/file-association/build/Taskfile.windows.yml (3)
24-28
: Consider adding validation steps to package task.The package task could benefit from additional steps to validate the installer after creation, such as checking file size and presence of required resources.
package: summary: Packages a production build of the application into a `.exe` bundle cmds: - task: create:nsis:installer + - cmd: | + if [ ! -f "{{.BIN_DIR}}/{{.APP_NAME}}-installer.exe" ]; then + echo "Installer not created successfully" + exit 1 + fi
37-49
: Add installer output path validation.While the installer creation is well-configured, it would be beneficial to validate the output path and ensure the installer is created successfully.
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 + - cmd: | + if [ ! -f "{{.APP_NAME}}-installer.exe" ]; then + echo "NSIS installer creation failed" + exit 1 + fi vars: ARCH: '{{.ARCH | default ARCH}}' ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}'
50-52
: Add error handling to run task.Consider adding basic error handling to ensure the executable exists before attempting to run it.
run: cmds: + - cmd: | + if [ ! -f "{{.BIN_DIR}}\\{{.APP_NAME}}.exe" ]; then + echo "Executable not found" + exit 1 + fi - '{{.BIN_DIR}}\\{{.APP_NAME}}.exe' +This change also addresses the missing newline at the end of file.
🧰 Tools
🪛 yamllint
[error] 52-52: no new line character at the end of file
(new-line-at-end-of-file)
v3/internal/commands/build_assets/Taskfile.common.yml (2)
71-75
: Consider enhancing task caching capabilities.While the task implementation is correct, consider adding
sources
andgenerates
declarations to enable Go-Task's caching mechanism. This would prevent unnecessary re-runs when inputs haven't changed.update:build-assets: summary: Updates the build assets dir: build + sources: + - config.yml + generates: + - .wails/**/* cmds: - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . +🧰 Tools
🪛 yamllint
[error] 75-75: no new line character at the end of file
(new-line-at-end-of-file)
75-75
: Add missing newline at end of file.Add a newline character at the end of the file to comply with POSIX standards and prevent potential issues with text processing tools.
🧰 Tools
🪛 yamllint
[error] 75-75: no new line character at the end of file
(new-line-at-end-of-file)
v3/examples/file-association/build/Taskfile.common.yml (6)
4-12
: Consider adding error handling for go mod tidy.While the task is well-structured, it might be good to add error handling to ensure the command executed successfully.
cmds: - - go mod tidy + - cmd: go mod tidy + silent: true + ignore_error: false
14-26
: Consider adding caching for npm dependencies.The task correctly handles dependencies, but build times could be improved by adding caching.
cmds: - - npm install + - cmd: npm ci + sources: + - package-lock.json + generates: + - node_modules/.package-lock.json
28-40
: Consider adding environment-specific build configurations.The build task could be enhanced to support different environments (development, production, etc.).
cmds: - - npm run build -q + - cmd: npm run build -q + env: + NODE_ENV: '{{.BUILD_ENV | default "production"}}'
41-51
: Add explicit error handling for bindings generation.The bindings generation is crucial for the application to work correctly. Consider adding explicit error handling.
cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}'{{if .UseTypescript}} -ts{{end}} + - cmd: wails3 generate bindings -f '{{.BUILD_FLAGS}}'{{if .UseTypescript}} -ts{{end}} + ignore_error: false
52-62
: Add input validation for icon generation.Consider adding validation for the input image to ensure it meets the requirements for both Windows and macOS icons.
cmds: + - cmd: test -f appicon.png + msg: "appicon.png not found in build directory" - wails3 generate icons -input appicon.png
63-70
: Add default port configuration.Consider adding a default port value to ensure the task works even if VITE_PORT is not set.
cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort + - npm run dev -- --port {{.VITE_PORT | default "3000"}} --strictPortv3/examples/file-association/build/Taskfile.linux.yml (2)
23-31
: Consider supporting additional Linux package formats.The package task currently only creates an AppImage. Consider:
- Adding support for .deb and .rpm packages for wider distribution
- Adding error checking for the build step before proceeding with packaging
64-66
: Enhance run task with validation and dev configuration.The run task could be improved with:
- Binary existence check
- Development-specific environment variables
- Optional debug flags
run: + deps: + - task: build cmds: + - test -f {{.BIN_DIR}}/{{.APP_NAME}} || (echo "Binary not found. Run build task first." && exit 1) - '{{.BIN_DIR}}/{{.APP_NAME}}' + env: + DEBUG: '{{.DEBUG | default "false"}}'mkdocs-website/docs/en/API/application_dialogs.md (3)
2-2
: Fix macOS capitalization in warning title.The operating system name should be written as "macOS" according to Apple's branding guidelines.
-!!! warning "MacOS Dialogs and Application Lifecycle" +!!! warning "macOS Dialogs and Application Lifecycle"🧰 Tools
🪛 LanguageTool
[grammar] ~2-~2: The operating system from Apple is written “macOS”.
Context: !!! warning "MacOS Dialogs and Application Lifecycle" ...(MAC_OS)
19-21
: Replace hard tabs with spaces for consistent formatting.The code example contains hard tabs which should be replaced with spaces for better consistency across different editors.
- app.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(event *application.ApplicationEvent) { - filename = event.Context().Filename() - }) + app.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(event *application.ApplicationEvent) { + filename = event.Context().Filename() + })🧰 Tools
🪛 Markdownlint
19-19: Column: 1
Hard tabs(MD010, no-hard-tabs)
20-20: Column: 1
Hard tabs(MD010, no-hard-tabs)
17-29
: Consider adding error handling to the code example.The example could be enhanced by demonstrating proper error handling for cases where the filename might be empty or invalid.
var filename string app.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(event *application.ApplicationEvent) { filename = event.Context().Filename() }) window.OnWindowEvent(events.Common.WindowShow, func(event *application.WindowEvent) { + if filename == "" { + return + } application.InfoDialog(). SetTitle("File Opened"). SetMessage("Application opened with file: " + filename). Show() })🧰 Tools
🪛 Markdownlint
19-19: Column: 1
Hard tabs(MD010, no-hard-tabs)
20-20: Column: 1
Hard tabs(MD010, no-hard-tabs)
v3/examples/file-association/main.go (3)
13-19
: Consider enhancing the documentation with file association details.While the current documentation explains the embed functionality well, it would be helpful to add information about which file types are supported for association (e.g., .wails files) since this is a file association example.
51-60
: Consider adding platform-specific window configurations for other operating systems.While the MacOS window configuration is comprehensive, the example would benefit from showing window configurations for other platforms (Windows/Linux) to demonstrate cross-platform file association handling.
85-90
: Consider more graceful error handling.Using
log.Fatal
immediately terminates the program. Consider implementing more graceful shutdown procedures, especially for cleaning up resources and handling any pending file operations.-if err != nil { - log.Fatal(err) -} +if err != nil { + log.Printf("Application error: %v", err) + // Perform cleanup if necessary + os.Exit(1) +}v3/examples/file-association/frontend/public/style.css (3)
18-23
: Consider a more selective approach to user-select: none.Applying
user-select: none
globally might impact accessibility and user experience. Consider applying it only to specific UI elements where text selection should be prevented (e.g., buttons, navigation items) while allowing text selection for content areas.-* { +.no-select { user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; }
25-31
: Optimize font loading strategy.Consider enhancing the font loading performance and behavior:
- Add woff2 format which offers better compression
- Include font-display property to control font loading behavior
@font-face { font-family: "Inter"; font-style: normal; font-weight: 400; + font-display: swap; src: local(""), - url("./Inter-Medium.ttf") format("truetype"); + url("./Inter-Medium.woff2") format("woff2"), + url("./Inter-Medium.ttf") format("truetype"); }
120-133
: Improve theme handling with CSS variables and transitions.Consider enhancing the theme implementation:
- Use CSS variables for theme colors
- Add smooth transitions for theme switching
:root { + --text-color: rgba(255, 255, 255, 0.87); + --bg-color: rgba(27, 38, 54, 1); + --link-hover-color: #535bf2; + --button-bg: transparent; + transition: all 0.3s ease; } @media (prefers-color-scheme: light) { :root { - color: #213547; - background-color: #ffffff; + --text-color: #213547; + --bg-color: #ffffff; + --link-hover-color: #747bff; + --button-bg: #f9f9f9; } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } } +body { + color: var(--text-color); + background-color: var(--bg-color); +} + +a:hover { + color: var(--link-hover-color); +} + +button { + background-color: var(--button-bg); +}v3/internal/commands/build_assets/nsis/project.nsi.tmpl (1)
94-95
: Consider adding logging for file association operations.To improve troubleshooting capabilities, consider adding detailed logging for file association and unassociation operations. This would help diagnose issues if file associations don't work as expected.
Example enhancement:
!insertmacro wails.associateFiles + DetailPrint "Registering file associations..." !insertmacro wails.unassociateFiles + DetailPrint "Removing file associations..."Also applies to: 109-110
v3/examples/file-association/build/nsis/project.nsi (1)
99-112
: Add user confirmation for data removal.Consider adding a confirmation dialog before removing user data:
Section "uninstall" !insertmacro wails.setShellContext + MessageBox MB_YESNO|MB_ICONQUESTION "Would you like to remove all application data?" IDNO skip_data_removal RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath + skip_data_removal:v3/internal/commands/build-assets.go (3)
37-39
: Consider reducing duplication between options structs.The
UpdateBuildAssetsOptions
duplicates all fields fromBuildAssetsOptions
. Consider using composition to reduce duplication and maintain consistency.type UpdateBuildAssetsOptions struct { - Dir string - Name string - BinaryName string - ProductName string - ProductDescription string - ProductVersion string - ProductCompany string - ProductCopyright string - ProductComments string - ProductIdentifier string + BuildAssetsOptions Config string Silent bool }Also applies to: 42-54
112-118
: Add documentation for FileAssociation fields.The
Role
field's purpose and valid values should be documented. Additionally, consider adding validation for theIconName
field to ensure the icon file exists.type FileAssociation struct { + // Ext is the file extension to associate with (e.g., ".txt") Ext string `yaml:"ext"` + // Name is the friendly name of the file type Name string `yaml:"name"` + // Description appears in file type selection dialogs Description string `yaml:"description"` + // IconName is the name of the icon file in the assets directory IconName string `yaml:"iconName"` + // Role specifies how the application handles this file type Role string `yaml:"role"` }
136-145
: Add config file path validation.While error handling is good, consider validating the config file path before attempting to read it.
if options.Config != "" { + if _, err := os.Stat(options.Config); os.IsNotExist(err) { + return fmt.Errorf("config file not found: %s", options.Config) + } bytes, err := os.ReadFile(options.Config) if err != nil { return err }mkdocs-website/docs/en/learn/guides/file-associations.md (4)
18-24
: Add prerequisite information for the configuration steps.Consider adding a note about prerequisites before the configuration steps, such as:
- Having Wails v3 installed
- Having initialized a Wails v3 project
- Location of the default
build
directory
28-40
: Add validation information for configuration properties.Consider adding information about:
- Required vs optional properties
- Valid values for the
role
property (e.g., what other roles besidesEditor
are supported?)- File extension format restrictions (e.g., max length, allowed characters)
132-133
: Enhance testing instructions.Consider adding more detailed testing instructions:
- How to verify file associations are correctly registered
- How to test file opening from different contexts (e.g., double-click, "Open with" menu)
- Platform-specific testing considerations
- Troubleshooting common issues
136-138
: Fix list formatting and expand additional notes.
- Fix the unordered list indentation.
- Consider adding more details about:
- Supported icon formats and sizes for each platform
- Best practices for icon design
- Installation verification steps
- Uninstallation considerations
-• Icons should be provided in PNG format in the build folder -• Testing file associations requires installing the packaged application +- Icons should be provided in PNG format in the build folder +- Testing file associations requires installing the packaged applicationv3/pkg/application/application_darwin_delegate.m (1)
12-17
: Consider adding event listener support for consistency.While the implementation is functionally correct, it differs from the pattern used by other methods in the file. Other application events use the
hasListeners
check andprocessApplicationEvent
pattern.Consider refactoring to match the established pattern:
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { const char* utf8FileName = filename.UTF8String; - HandleOpenFile((char*)utf8FileName); + if (hasListeners(EventApplicationOpenFile)) { + NSString *filePath = [NSString stringWithUTF8String:utf8FileName]; + processApplicationEvent(EventApplicationOpenFile, @{@"filename": filePath}); + } return YES; }v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts (1)
192-192
: Consider adding events for runtime file associations.While
ApplicationOpenedWithFile
handles the initial file open scenario, consider adding events for file associations during runtime (e.g., when files are opened with the application while it's already running). This would provide a more complete file association feature.Suggested additional events:
Common: { // ... existing events ... ApplicationOpenedWithFile: string, + ApplicationFileOpened: string, // For files opened while app is running + ApplicationFileAssociationChanged: string, // For dynamic file association changes },v3/internal/commands/updatable_build_assets/nsis/wails_tools.nsh.tmpl (1)
181-217
: Consider architectural improvements for robustness.While the file association implementation is fundamentally sound, consider these architectural improvements:
- Add a validation phase before installation to check all required files exist.
- Implement rollback functionality in case of failures during association/unassociation.
- Consider logging all registry operations to aid in troubleshooting.
Would you like assistance in implementing any of these improvements?
v3/examples/file-association/build/nsis/wails_tools.nsh (3)
10-12
: Consider improving default company name.The default company name "My Company" might be confusing for users. Consider using a more descriptive default or requiring this value to be explicitly set.
- !define INFO_COMPANYNAME "My Company" + !define INFO_COMPANYNAME "Unknown Company"
100-112
: Add file existence validation.The macro should validate that the binary files exist before attempting to copy them.
!macro wails.files !ifdef SUPPORTS_AMD64 ${if} ${IsNativeAMD64} + !tempfile BINARY_CHECK + !system 'if not exist "${ARG_WAILS_AMD64_BINARY}" echo !error "AMD64 binary not found: ${ARG_WAILS_AMD64_BINARY}" > "${BINARY_CHECK}"' + !include "${BINARY_CHECK}" File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" ${EndIf} !endif
137-143
: Add documentation for shell context settings.Consider adding comments explaining the implications of different shell contexts for better maintainability.
!macro wails.setShellContext + # Set shell context to 'all users' for admin installs + # or 'current user' for non-admin installs ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" SetShellVarContext all ${else} SetShellVarContext current ${EndIf} !macroendv3/pkg/application/application_options.go (2)
112-115
: LGTM! Consider adding validation for file extensions.The
FileAssociations
field is well-documented with a clear example. However, consider adding runtime validation to ensure:
- Each extension starts with a '.'
- No duplicate extensions
- Valid characters in extensions
Example validation implementation:
// ValidateFileAssociations validates file extensions func ValidateFileAssociations(extensions []string) error { seen := make(map[string]bool) for _, ext := range extensions { if !strings.HasPrefix(ext, ".") { return fmt.Errorf("file extension must start with '.': %s", ext) } if seen[ext] { return fmt.Errorf("duplicate file extension: %s", ext) } // Basic validation for valid characters if !regexp.MustCompile(`^\.[a-zA-Z0-9]+$`).MatchString(ext) { return fmt.Errorf("invalid characters in extension: %s", ext) } seen[ext] = true } return nil }
112-115
: Document platform-specific behaviors for file associations.Since file associations can behave differently across platforms (Windows, macOS, Linux), consider expanding the documentation to cover:
- Platform-specific file association mechanisms
- Any limitations or special considerations per platform
- How the associations are registered with the OS
Example documentation:
// FileAssociations defines the file extensions to associate with this application. // Platform-specific behavior: // - Windows: Registers associations in the Windows Registry // - macOS: Updates the Info.plist CFBundleDocumentTypes // - Linux: Updates the .desktop file's MimeType entry // Example: [".txt", ".md"] // Note: The '.' prefix is required for all extensionsv3/pkg/application/application_windows.go (1)
140-144
: Remove debug print statements.Debug print statements should be replaced with proper logging using the application's logging system.
-println("Checking args") -println("Got extension: ", ext)v3/pkg/application/dialogs_darwin.go (1)
32-34
: Potential memory leak in icon handlingThe NSImage created from the icon data is not being released. While ARC might handle this in modern macOS versions, it's good practice to be explicit about ownership.
Consider managing the image lifecycle:
if (icon != NULL) { - NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; - [alert setIcon:image]; + @autoreleasepool { + NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; + [alert setIcon:image]; + } }mkdocs-website/docs/en/changelog.md (1)
Line range hint
1-24
: Consider enhancing the file association entry with more details.While the current entry follows the changelog format, consider adding a brief description of the file association feature's key capabilities to help users understand its impact. For example:
-File Association support by [leaanthony](https://github.com/leaanthony) in [#3873](https://github.com/wailsapp/wails/pull/3873) +File Association support - Enable applications to handle specific file types by [leaanthony](https://github.com/leaanthony) in [#3873](https://github.com/wailsapp/wails/pull/3873)Also applies to: 24-500
v3/pkg/application/webview_window_darwin.go (1)
Line range hint
1251-1263
: Consider setting window properties before showing the window.The current implementation sets the shadow and always-on-top properties after making the window visible, which could potentially cause brief visual artifacts. While the impact is likely minimal due to the immediate execution, consider this alternative approach for a smoother visual experience:
- w.parent.Show() - w.setHasShadow(!options.Mac.DisableShadow) - w.setAlwaysOnTop(options.AlwaysOnTop) + w.setHasShadow(!options.Mac.DisableShadow) + w.setAlwaysOnTop(options.AlwaysOnTop) + w.parent.Show()v3/pkg/application/webview_window_windows.go (1)
Line range hint
1-1200
: Consider breaking down therun()
methodThe
run()
method is quite long and handles multiple responsibilities including window creation, chromium setup, theme processing, and more. Consider breaking it down into smaller, focused methods for better maintainability.Example refactor:
func (w *windowsWebviewWindow) run() { w.initializeWindow() w.setupChromium() w.configureWindowProperties() w.finalizeSetup() } +func (w *windowsWebviewWindow) initializeWindow() { + // Window creation and basic setup +} +func (w *windowsWebviewWindow) configureWindowProperties() { + // Theme, size constraints, etc. +} +func (w *windowsWebviewWindow) finalizeSetup() { + // Final visibility and update +}
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
⛔ Files ignored due to path filters (7)
v3/examples/file-association/build/appicon.png
is excluded by!**/*.png
v3/examples/file-association/build/icon.ico
is excluded by!**/*.ico
v3/examples/file-association/frontend/package-lock.json
is excluded by!**/package-lock.json
v3/examples/file-association/frontend/public/Inter-Medium.ttf
is excluded by!**/*.ttf
v3/examples/file-association/frontend/public/javascript.svg
is excluded by!**/*.svg
v3/examples/file-association/frontend/public/wails.png
is excluded by!**/*.png
v3/examples/file-association/go.sum
is excluded by!**/*.sum
📒 Files selected for processing (56)
mkdocs-website/docs/en/API/application_dialogs.md
(1 hunks)mkdocs-website/docs/en/changelog.md
(1 hunks)mkdocs-website/docs/en/learn/guides/file-associations.md
(1 hunks)mkdocs-website/docs/en/status.md
(2 hunks)mkdocs-website/mkdocs.yml
(1 hunks)v3/examples/file-association/.gitignore
(1 hunks)v3/examples/file-association/Inter Font License.txt
(1 hunks)v3/examples/file-association/README.md
(1 hunks)v3/examples/file-association/Taskfile.yml
(1 hunks)v3/examples/file-association/build/Info.dev.plist
(1 hunks)v3/examples/file-association/build/Info.plist
(1 hunks)v3/examples/file-association/build/Taskfile.common.yml
(1 hunks)v3/examples/file-association/build/Taskfile.darwin.yml
(1 hunks)v3/examples/file-association/build/Taskfile.linux.yml
(1 hunks)v3/examples/file-association/build/Taskfile.windows.yml
(1 hunks)v3/examples/file-association/build/appimage/build.sh
(1 hunks)v3/examples/file-association/build/config.yml
(1 hunks)v3/examples/file-association/build/devmode.config.yaml
(1 hunks)v3/examples/file-association/build/info.json
(1 hunks)v3/examples/file-association/build/nsis/project.nsi
(1 hunks)v3/examples/file-association/build/nsis/wails_tools.nsh
(1 hunks)v3/examples/file-association/build/wails.exe.manifest
(1 hunks)v3/examples/file-association/frontend/bindings/changeme/greetservice.js
(1 hunks)v3/examples/file-association/frontend/bindings/changeme/index.js
(1 hunks)v3/examples/file-association/frontend/index.html
(1 hunks)v3/examples/file-association/frontend/main.js
(1 hunks)v3/examples/file-association/frontend/package.json
(1 hunks)v3/examples/file-association/frontend/public/style.css
(1 hunks)v3/examples/file-association/go.mod
(1 hunks)v3/examples/file-association/greetservice.go
(1 hunks)v3/examples/file-association/main.go
(1 hunks)v3/examples/file-association/test.wails
(1 hunks)v3/internal/commands/build-assets.go
(6 hunks)v3/internal/commands/build_assets/Taskfile.common.yml
(1 hunks)v3/internal/commands/build_assets/appdata.tmpl.yaml
(0 hunks)v3/internal/commands/build_assets/config.yml
(1 hunks)v3/internal/commands/build_assets/nsis/project.nsi.tmpl
(2 hunks)v3/internal/commands/updatable_build_assets/Info.dev.plist.tmpl
(1 hunks)v3/internal/commands/updatable_build_assets/Info.plist.tmpl
(1 hunks)v3/internal/commands/updatable_build_assets/nsis/wails_tools.nsh.tmpl
(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/package.json
(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js
(1 hunks)v3/internal/runtime/desktop/@wailsio/runtime/types/event_types.d.ts
(1 hunks)v3/pkg/application/application_darwin.go
(1 hunks)v3/pkg/application/application_darwin_delegate.h
(1 hunks)v3/pkg/application/application_darwin_delegate.m
(1 hunks)v3/pkg/application/application_options.go
(1 hunks)v3/pkg/application/application_windows.go
(2 hunks)v3/pkg/application/context_application_event.go
(2 hunks)v3/pkg/application/dialogs_darwin.go
(1 hunks)v3/pkg/application/webview_window_darwin.go
(1 hunks)v3/pkg/application/webview_window_windows.go
(1 hunks)v3/pkg/events/events.go
(4 hunks)v3/pkg/events/events.txt
(1 hunks)v3/tasks/events/generate.go
(2 hunks)v3/tasks/events/go.mod
(1 hunks)
💤 Files with no reviewable changes (1)
- v3/internal/commands/build_assets/appdata.tmpl.yaml
✅ Files skipped from review due to trivial changes (12)
- v3/examples/file-association/.gitignore
- v3/examples/file-association/build/Info.dev.plist
- v3/examples/file-association/build/Info.plist
- v3/examples/file-association/build/info.json
- v3/examples/file-association/build/wails.exe.manifest
- v3/examples/file-association/frontend/bindings/changeme/greetservice.js
- v3/examples/file-association/frontend/bindings/changeme/index.js
- v3/examples/file-association/frontend/index.html
- v3/examples/file-association/frontend/package.json
- v3/examples/file-association/test.wails
- v3/internal/runtime/desktop/@wailsio/runtime/package.json
- v3/tasks/events/go.mod
🧰 Additional context used
🪛 LanguageTool
mkdocs-website/docs/en/API/application_dialogs.md
[grammar] ~2-~2: The operating system from Apple is written “macOS”.
Context: !!! warning "MacOS Dialogs and Application Lifecycle" ...
(MAC_OS)
v3/examples/file-association/Inter Font License.txt
[typographical] ~9-~9: If you want to indicate numerical ranges or time ranges, consider using an en dash.
Context: ...------ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 -----------------------...
(DASH_RULE)
🪛 Markdownlint
mkdocs-website/docs/en/API/application_dialogs.md
19-19: Column: 1
Hard tabs
(MD010, no-hard-tabs)
20-20: Column: 1
Hard tabs
(MD010, no-hard-tabs)
mkdocs-website/docs/en/learn/guides/file-associations.md
79-79: Expected: 0; Actual: 3
Unordered list indentation
(MD007, ul-indent)
80-80: Expected: 0; Actual: 3
Unordered list indentation
(MD007, ul-indent)
81-81: Expected: 0; Actual: 3
Unordered list indentation
(MD007, ul-indent)
59-59: Column: 1
Hard tabs
(MD010, no-hard-tabs)
60-60: Column: 1
Hard tabs
(MD010, no-hard-tabs)
62-62: Column: 1
Hard tabs
(MD010, no-hard-tabs)
63-63: Column: 1
Hard tabs
(MD010, no-hard-tabs)
64-64: Column: 1
Hard tabs
(MD010, no-hard-tabs)
66-66: Column: 1
Hard tabs
(MD010, no-hard-tabs)
67-67: Column: 1
Hard tabs
(MD010, no-hard-tabs)
68-68: Column: 1
Hard tabs
(MD010, no-hard-tabs)
69-69: Column: 1
Hard tabs
(MD010, no-hard-tabs)
114-114: Column: 1
Hard tabs
(MD010, no-hard-tabs)
115-115: Column: 1
Hard tabs
(MD010, no-hard-tabs)
116-116: Column: 1
Hard tabs
(MD010, no-hard-tabs)
121-121: Expected: fenced; Actual: indented
Code block style
(MD046, code-block-style)
v3/examples/file-association/README.md
4-4: null
Bare URL used
(MD034, no-bare-urls)
🪛 yamllint
v3/examples/file-association/build/Taskfile.common.yml
[error] 75-75: no new line character at the end of file
(new-line-at-end-of-file)
v3/examples/file-association/build/Taskfile.windows.yml
[error] 52-52: no new line character at the end of file
(new-line-at-end-of-file)
v3/examples/file-association/build/config.yml
[error] 32-32: no new line character at the end of file
(new-line-at-end-of-file)
v3/internal/commands/build_assets/Taskfile.common.yml
[error] 75-75: no new line character at the end of file
(new-line-at-end-of-file)
v3/internal/commands/build_assets/config.yml
[error] 32-32: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (63)
v3/pkg/application/application_darwin_delegate.h (1)
8-8
: Verify the impact of changing the base class to NSResponder.
The change from NSObject
to NSResponder
is appropriate for handling file open events, but this could potentially affect existing applications.
Let's verify the impact:
✅ Verification successful
Let's gather more information about the implementations to understand the impact better.
Let's check the implementation file to fully understand the impact.
Base class change from NSObject to NSResponder is safe and consistent with existing implementation
The verification shows that:
- The v2 implementation already uses NSResponder as the base class
- The change in v3 is actually maintaining compatibility with v2, not introducing a breaking change
- The implementation properly uses NSResponder features for event handling, particularly for file open events
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any custom implementations or extensions of AppDelegate
# that might be affected by the base class change
rg -l "AppDelegate.*:" --type objc
Length of output: 135
Script:
#!/bin/bash
# Check the content of both files to compare implementations
echo "=== v3 AppDelegate Implementation ==="
cat v3/pkg/application/application_darwin_delegate.h
echo -e "\n=== v2 AppDelegate Implementation ==="
cat v2/internal/frontend/desktop/darwin/AppDelegate.h
# Also check for any implementation files (.m)
echo -e "\n=== Implementation files ==="
fd -e m "AppDelegate"
Length of output: 1497
Script:
#!/bin/bash
# Check the v2 implementation to understand how NSResponder is used
cat v2/internal/frontend/desktop/darwin/AppDelegate.m
# Also search for any references to AppDelegate methods in the codebase
rg "AppDelegate.*\]" --type objc -A 2
Length of output: 2998
v3/examples/file-association/README.md (1)
1-3
: LGTM!
The title and introduction clearly communicate the purpose of the sample project.
v3/examples/file-association/frontend/main.js (1)
1-2
: Verify the import path for bindings
The import path contains a placeholder "changeme" which might need to be updated to the correct package name.
✅ Verification successful
The import path "./bindings/changeme" is correct and valid
The import path is actually correct as the file exists at the expected location and exports the GreetService
as required. The "changeme" directory appears to be intentional as it contains the auto-generated bindings with proper exports.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if the import path exists and verify its structure
fd --type f "index.js" --exec grep -l "GreetService" {}
Length of output: 14575
Script:
#!/bin/bash
# Let's check the content of the bindings/changeme/index.js file to verify if it's a valid binding
cat v3/examples/file-association/frontend/bindings/changeme/index.js
Length of output: 276
v3/examples/file-association/build/devmode.config.yaml (2)
1-28
: Verify integration with file association features.
As this is part of the file association example, we should ensure this development configuration properly supports file association testing.
Let's check for file association configurations in the example:
✅ Verification successful
Development configuration aligns with file association implementation
The development configuration (devmode.config.yaml
) is correctly set up to support file association testing:
- It properly watches Go files for changes (
*.go
in watched_extension) - The execution chain includes all necessary build and run commands
- The main configuration file (
config.yml
) in the same directory confirms file association support with proper configuration for.wails
files - The development mode will properly rebuild and reload the application when file association related code changes are made
The configuration is sufficient for developing and testing file association features in this example project.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify file association configuration presence and structure
# Expected: Find file association configurations and related build settings
# Check for file association configurations in build directory
echo "Checking for file association configurations..."
rg -l "file.*association" build/
# Look for related build settings
echo "Checking for build settings..."
rg -l "build.*assets" .
# Check for platform-specific file association implementations
echo "Checking for platform-specific implementations..."
rg -l "RegisterFileAssociation|HandleFileOpen" .
Length of output: 11924
Script:
#!/bin/bash
# Let's check the file association example directory structure and configuration files
# Check the example's directory structure
echo "File Association Example Structure:"
fd . v3/examples/file-association/
# Check the main configuration file
echo -e "\nMain Configuration File:"
cat v3/examples/file-association/build/config.yml
# Check for file association related code in the example
echo -e "\nSearching for file association related code:"
rg -l "fileAssociation|HandleFile" v3/examples/file-association/
Length of output: 3561
5-17
: Verify file watching configuration for file association example.
The current configuration only watches .go
files, but for a file association example, we might need to watch additional file types:
- Frontend changes might be relevant for file handling UI
- File association configuration files might have different extensions
Let's check what file types are actually used in this example:
✅ Verification successful
Let me gather more information about the actual file types used in this example.
This will help us understand:
- All file types actually used in the example
- Any code files that handle file associations to determine relevant file types to watch
Let me check the specific files in the file-association example to understand what file types are actually used.
This will help us understand what file types are actually used in this example and what the example is meant to demonstrate.
Current file watching configuration is appropriate for this example
The current configuration watching only .go
files is actually correct for this example because:
- The example demonstrates file association functionality where the app handles
.wails
files (as shown bytest.wails
in the example) - The file association is configured through build configuration files (
.yaml
,.yml
,.json
) which are correctly excluded as they are build-time configurations - Frontend files are correctly ignored as they are handled by the frontend build process
- The core functionality for handling associated files is implemented in the Go files, which are properly watched
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check what file types are used in the example
# Expected: Find files that might need to be watched for the file association example
# Look for potential file association configuration files
fd -e yaml -e json -e toml . | grep -i "assoc"
# Check frontend file types that might need watching
fd . frontend/ -t f 2>/dev/null || echo "Frontend directory not found"
Length of output: 342
Script:
#!/bin/bash
# Check all file types in the file-association example directory
fd . v3/examples/file-association/ -t f -x file {} | sort
# Check if there are any file association related code files
rg -l "fileAssociation|file.*association" -g "!*.{json,yaml}" -A 3
Length of output: 9553
Script:
#!/bin/bash
# List all files in the file-association example directory
fd . v3/examples/file-association/ -t f
# Check the README for any mentions of file types
cat v3/examples/file-association/README.md
Length of output: 2308
v3/examples/file-association/Taskfile.yml (3)
14-29
: LGTM! Cross-platform task delegation is well structured.
The build, package, and run tasks are properly delegated to OS-specific implementations using the {{OS}}
variable, ensuring consistent behavior across platforms.
1-7
: Verify the existence of referenced task files.
The configuration references several task files that should exist in the ./build
directory.
#!/bin/bash
# Description: Verify that all referenced task files exist
# Expected: All task files should be present in the build directory
echo "Checking for referenced task files..."
for file in "Taskfile.common.yml" "Taskfile.windows.yml" "Taskfile.darwin.yml" "Taskfile.linux.yml"; do
if fd -p "build/$file$" v3/examples/file-association/; then
echo "✓ Found $file"
else
echo "✗ Missing $file"
fi
done
30-33
: Verify the devmode config file existence and port configuration.
The dev task references a specific config file and uses the VITE_PORT variable.
✅ Verification successful
Configuration files and port settings are properly set up
The verification shows that:
- The devmode.config.yaml exists and contains valid configuration
- VITE_PORT is properly defined in Taskfile.yml with a default value of 9245
- The port configuration is correctly used in both the dev task and frontend tasks
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the devmode config file exists and check its content
# Expected: Config file should exist and contain valid configuration
echo "Checking for devmode config file..."
if fd -p "build/devmode\.config\.yaml$" v3/examples/file-association/; then
echo "✓ Found devmode.config.yaml"
echo "Checking config content..."
cat v3/examples/file-association/build/devmode.config.yaml
else
echo "✗ Missing devmode.config.yaml"
fi
Length of output: 1529
Script:
#!/bin/bash
# Let's verify the devmode config file and VITE_PORT variable in a more focused way
# Check for devmode.config.yaml
echo "Checking for devmode config file..."
fd -p "devmode\.config\.yaml$" v3/examples/file-association/
# Check for VITE_PORT variable in any relevant files
echo -e "\nChecking for VITE_PORT variable definition..."
rg "VITE_PORT" v3/examples/file-association/ -A 2
# Check for any other config files that might contain port configuration
echo -e "\nChecking for other config files with port configuration..."
rg "port:" v3/examples/file-association/ --type yaml -A 2
Length of output: 1102
Script:
#!/bin/bash
# Let's check the content of the devmode.config.yaml file since we found it exists
echo "Checking devmode.config.yaml content..."
cat v3/examples/file-association/build/devmode.config.yaml
# Also check the default port value in any environment files
echo -e "\nChecking for default port configurations..."
rg "WAILS_VITE_PORT" v3/examples/file-association/ -A 2
Length of output: 1044
v3/internal/commands/updatable_build_assets/Info.plist.tmpl (1)
9-9
: LGTM! Variable rename improves clarity.
The change from {{.Binary}}
to {{.BinaryName}}
makes the template variable more descriptive and aligns with the broader restructuring of build configurations.
Let's verify that this template variable is consistently used across the codebase:
✅ Verification successful
Based on the search results, I can now generate the final response:
Template variable change is consistently used across the codebase
The change from {{.Binary}}
to {{.BinaryName}}
is consistently implemented. The search results show:
- No instances of the old
{{.Binary}}
template variable remain in the codebase - The new
{{.BinaryName}}
is used in both Info.plist templates:- v3/internal/commands/updatable_build_assets/Info.plist.tmpl
- v3/internal/commands/updatable_build_assets/Info.dev.plist.tmpl
- The variable is also consistently used in various wails.tmpl.json files across different templates
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining instances of the old Binary template variable
# and confirm consistent usage of the new BinaryName variable in template files
# Test 1: Check for any remaining instances of the old Binary template variable
echo "Checking for old Binary template variable..."
rg '{{\.Binary}}'
# Test 2: Verify consistent usage of new BinaryName template variable
echo "Verifying usage of new BinaryName template variable..."
rg '{{\.BinaryName}}'
Length of output: 441
Script:
#!/bin/bash
# Description: Check for template variables with proper regex escaping
# and confirm consistent usage across the codebase
# Test 1: Check for any remaining instances of the old Binary template variable
echo "Checking for old Binary template variable..."
rg '\{\{\.Binary\}\}'
# Test 2: Verify consistent usage of new BinaryName template variable
echo "Verifying usage of new BinaryName template variable..."
rg '\{\{\.BinaryName\}\}'
# Test 3: Check all template files for context
echo "Checking all template files..."
fd -e tmpl -x cat {}
Length of output: 74890
v3/internal/commands/updatable_build_assets/Info.dev.plist.tmpl (1)
9-9
: LGTM! Verify template consistency across the codebase.
The change from {{.Binary}}
to {{.BinaryName}}
aligns with the broader restructuring of configuration options.
Let's verify if all plist templates are consistently using the new variable name:
✅ Verification successful
Template variable change is consistent and correct
The verification shows that the change from {{.Binary}}
to {{.BinaryName}}
in Info.dev.plist.tmpl
is correct and consistent with the codebase structure:
- The new
{{.BinaryName}}
variable is used consistently in v3's template files underinternal/commands/updatable_build_assets/
- Other v3 template files use similar naming patterns (e.g.,
{{.ProjectName}}
in base templates) - No instances of the old
{{.Binary}}
variable were found in any plist templates - The change aligns with the v3 codebase's template variable naming conventions
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any remaining instances of the old Binary variable
# and ensure BinaryName is used consistently across plist templates
# Search for any remaining instances of the old Binary variable in plist templates
rg -l '{{.Binary}}' --glob '*.plist*'
# Show usage of the new BinaryName variable in plist templates for context
rg -l '{{.BinaryName}}' --glob '*.plist*'
Length of output: 1278
Script:
#!/bin/bash
# Let's try a different approach to search for template variables in plist files
# Search for any plist template files first
fd -e plist.tmpl -e plist
# Then examine their content focusing on CFBundleExecutable sections
rg -A 2 -B 2 'CFBundleExecutable' --glob '*.plist*'
# Also search for any template variables with proper escaping
rg '\{\{\..*?\}\}' --glob '*.plist*'
Length of output: 14363
mkdocs-website/docs/en/status.md (1)
3-3
: Version update aligns with feature additions.
The increment from Alpha 6 to Alpha 7 appropriately reflects the ongoing development progress, particularly with the addition of file association support as mentioned in the PR objectives.
v3/examples/file-association/build/Taskfile.darwin.yml (3)
1-5
: LGTM! Good separation of concerns.
The file structure follows Task best practices by separating common tasks into a separate file.
7-25
: Verify minimum macOS version compatibility.
The build configuration sets macOS 10.15 as the minimum deployment target. Ensure this aligns with the project's compatibility requirements and user base needs.
Consider adding code signing configuration.
For macOS applications, especially those with file associations, code signing is crucial for proper functionality and security. Consider adding code signing steps to the build process.
Example addition:
BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l"{{end}}'
+SIGN_FLAGS: '--sign "Developer ID Application: Your Name (TEAM_ID)" --options runtime'
26-34
: LGTM! Good task organization.
The package task correctly ensures a production build before creating the app bundle.
v3/pkg/application/context_application_event.go (1)
59-73
: Verify consistent usage of file association events.
The implementation looks good but let's verify the usage patterns across the codebase to ensure consistency.
✅ Verification successful
Based on the shell script results, I can now provide a final response:
File association implementation is correctly used across the codebase
The implementation aligns well with the codebase usage patterns:
- Consistent event handling in platform-specific code (Darwin, Windows)
- Proper event type registration in the events package
- Documented usage in examples and guides
- No direct access to the internal data map, ensuring proper encapsulation
- Consistent usage pattern through
event.Context().Filename()
in consumer code
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check usage patterns of file association methods
# Check for event handling implementations
echo "Checking event handling implementations..."
rg -A 5 "ApplicationOpenedWithFile|setOpenedWithFile|Filename\(\)"
# Check for potential direct access to the filename constant
echo "Checking for direct data map access..."
rg "data\[\"filename\"\]|data\['filename'\]"
Length of output: 5869
v3/examples/file-association/build/Taskfile.windows.yml (3)
1-5
: LGTM! Well-structured task organization.
Good practice using task includes for common functionality, promoting code reuse and maintainability.
29-36
: LGTM! Well-configured Windows resource generation.
The task correctly generates the Windows resource file with all necessary components (icon, manifest, and info).
7-23
: Verify CGO requirements for file associations.
The build configuration looks solid, but setting CGO_ENABLED=0
might affect file association functionality on Windows. Some Windows API calls might require CGO.
Let's verify if any CGO-dependent code is used:
v3/internal/commands/build_assets/Taskfile.common.yml (1)
69-70
: LGTM: Well-structured Vite development server configuration.
The command correctly uses the --strictPort
flag to ensure consistent port binding, which is important for reliable development workflow.
v3/examples/file-association/build/Taskfile.common.yml (1)
1-3
: LGTM: File structure and version specification are correct.
v3/examples/file-association/build/Taskfile.linux.yml (3)
1-5
: LGTM! Good use of task composition.
The file structure follows best practices by including common tasks from a shared file, promoting code reuse.
51-63
: Make desktop file generation more configurable.
Consider these improvements:
- Make categories configurable via variables instead of hardcoding "Development"
- Add validation for icon file existence
- Consider supporting additional .desktop file fields (MimeType, etc.) for file associations
7-22
: Verify build configuration and enhance documentation.
While the build task is well-structured, consider the following improvements:
- Document why CGO_ENABLED=1 is required
- Specify the default ARCH value in the task description
- Consider documenting the implications of -trimpath in production builds
✅ Verification successful
Let me analyze the results and generate additional verification scripts to better understand the CGO usage and architecture-specific requirements.
The first script will help understand why CGO is needed on Linux, the second will show architecture-specific build configurations, and the third will look for any existing documentation about CGO requirements.
Based on the results from the shell scripts, I can now provide a complete analysis of the build configuration:
CGO and architecture configuration documented
- CGO_ENABLED=1 is required for Linux builds as it uses GTK and WebKit bindings for the native UI components
- ARCH parameter is properly handled with a default fallback
- -trimpath is used in production builds for better security
The build configuration is well-structured and the CGO requirement is justified by the GTK/WebKit dependencies shown in the Linux-specific files.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check if any C dependencies are actually used in the project
rg -l 'import "C"'
# Verify architecture-specific code
rg -l 'GOARCH|386|amd64|arm64'
Length of output: 39038
Script:
#!/bin/bash
# Check for CGO dependencies in Linux-specific files
rg -l "import \"C\"" | grep -i "linux" | xargs rg -l "gtk|webkit|x11|xcb"
# Check for architecture-specific code in build files
rg -l "GOARCH|386|amd64|arm64" | grep -i "build" | xargs cat
# Look for documentation about CGO requirements
rg -i "cgo.*required|cgo.*needed"
Length of output: 185729
v3/examples/file-association/go.mod (4)
7-8
: LGTM!
The Wails v3 dependency is correctly specified with an appropriate alpha version for development.
9-50
: LGTM!
The indirect dependencies are well-structured with pinned versions, covering all necessary functionality for file associations including crypto, file handling, and UI operations.
52-52
: LGTM!
The replace directive correctly points to the local Wails v3 development path, which is appropriate for an example within the repository.
1-5
: Consider version consistency and module naming.
- There's a mismatch between the Go version (1.22.4) and toolchain version (1.23.0). Consider aligning these versions.
- The module name "changeme" appears to be a placeholder. While this might be intentional for an example, consider documenting that users should replace this with their own module name.
mkdocs-website/docs/en/API/application_dialogs.md (1)
4-13
: LGTM! Clear explanation with helpful code example.
The warning effectively communicates an important configuration requirement for macOS applications, and the code example clearly demonstrates the proper implementation.
v3/examples/file-association/main.go (2)
3-12
: LGTM: Imports are appropriate and well-organized.
The imports include all necessary packages for file association functionality, event handling, and frontend asset embedding.
31-44
: Verify GreetService implementation and consider documenting supported file types.
- The code references
GreetService
but its implementation isn't visible in the current context. - The file association is limited to ".wails" files. Consider documenting whether this is intentional or if it should support multiple file types.
✅ Verification successful
Let me gather more information about the GreetService implementation in the file-association example and the file association documentation.
GreetService implementation and file associations are properly configured
The implementation is correct and well-documented:
- The
GreetService
ingreetservice.go
is properly implemented with aGreet
method. - The single
.wails
file association is intentional as this is an example application demonstrating the feature. - The documentation clearly explains that file associations need to be configured both in
config.yml
and application options, which is followed in this example.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for GreetService implementation
ast-grep --pattern 'type GreetService struct {
$$$
}'
# Check for any other file association examples
rg -l "FileAssociations.*\[.*\].*string"
Length of output: 6505
Script:
#!/bin/bash
# Check GreetService implementation in the file-association example
cat v3/examples/file-association/greetservice.go
# Check file association documentation
cat mkdocs-website/docs/en/learn/guides/file-associations.md
# Check application options definition for FileAssociations
cat v3/pkg/application/application_options.go | grep -A 5 "FileAssociations"
Length of output: 5268
v3/internal/commands/build_assets/nsis/project.nsi.tmpl (2)
109-110
: Verify the wails.unassociateFiles macro implementation.
The placement of the unassociation macro is correct, being called during cleanup but before removing the uninstaller. This ensures proper cleanup of file associations during uninstallation.
✅ Verification successful
The wails.unassociateFiles macro implementation is correct and properly handles file association cleanup
The macro implementation in wails_tools.nsh.tmpl
correctly:
- Iterates through all registered file associations using the template range construct
- Uses
APP_UNASSOCIATE
macro to remove each file association from the registry - Cleans up associated icon files from the installation directory
The placement in the uninstall section of project.nsi.tmpl
is appropriate, ensuring file associations are removed before the final uninstaller cleanup.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the wails.unassociateFiles macro implementation
# Look for the macro definition in wails_tools.nsh
rg -A 10 "macro wails.unassociateFiles"
Length of output: 3341
94-95
: Verify the wails.associateFiles macro implementation.
The placement of the file association macro is correct, being called after file installation but before writing the uninstaller. However, we should verify the implementation of this macro.
✅ Verification successful
The wails.associateFiles macro implementation is correctly ported from v2 to v3
The macro implementation in v3/internal/commands/updatable_build_assets/nsis/wails_tools.nsh.tmpl
correctly:
- Creates file associations using the APP_ASSOCIATE macro
- Iterates over FileAssociations to set up each association
- Copies the required icon files
- Maintains the same functionality as the v2 implementation
The placement in the installation section is also correct, being called after file installation but before writing the uninstaller.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the wails.associateFiles macro implementation
# Look for the macro definition in wails_tools.nsh
rg -A 10 "macro wails.associateFiles"
Length of output: 5803
v3/pkg/events/events.txt (1)
183-183
: LGTM! Consider platform-specific variants if needed.
The new ApplicationOpenedWithFile
event under the common
namespace is well-placed for cross-platform file association support. The naming is clear and follows conventions.
Let's verify there are no similar existing events and check if platform-specific variants exist:
✅ Verification successful
Event implementation is consistent across platforms
The ApplicationOpenedWithFile
event is:
- Properly defined in
events.go
with a unique ID (1206) - Consistently implemented in both Darwin and Windows platforms
- No duplicate or conflicting events found (only related but distinct events like
WindowFilesDropped
exist) - Appropriately categorized under
common
as it's implemented cross-platform
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for similar file-related events and platform-specific variants
# Test 1: Search for similar file-related events
echo "Checking for similar file-related events:"
rg -i "file|open" v3/pkg/events/events.txt
# Test 2: Check if platform-specific variants exist in other files
echo "Checking for platform-specific variants in implementation files:"
rg -l "ApplicationOpenedWithFile" v3/pkg/
Length of output: 701
Script:
#!/bin/bash
# Let's examine the implementation in platform-specific files to ensure consistency
echo "Checking Darwin implementation:"
rg -C 5 "ApplicationOpenedWithFile" v3/pkg/application/application_darwin.go
echo -e "\nChecking Windows implementation:"
rg -C 5 "ApplicationOpenedWithFile" v3/pkg/application/application_windows.go
echo -e "\nChecking event definition:"
rg -C 2 "ApplicationOpenedWithFile" v3/pkg/events/events.go
Length of output: 1383
mkdocs-website/mkdocs.yml (1)
153-153
: LGTM! Documentation entry is well-structured.
The new entry for File Associations guide is correctly placed under the Guides section and follows the established documentation structure.
Let's verify that the referenced guide file exists:
✅ Verification successful
✓ File association guide exists at the expected location
The referenced documentation file file-associations.md
exists at the correct path under mkdocs-website/docs/en/learn/guides/
, confirming that the navigation entry in mkdocs.yml
is valid.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the existence of the file associations guide
# Expected: The guide file should exist at the specified path
fd "file-associations.md" mkdocs-website/docs/en/learn/guides/
Length of output: 119
v3/examples/file-association/build/nsis/project.nsi (4)
1-50
: LGTM! Well-structured configuration with proper documentation.
The configuration section follows Windows installer best practices:
- Unicode support enabled for proper character handling
- Comprehensive documentation for manual debugging
- Proper version information structure (4-part version)
- HiDPI support enabled for modern displays
73-77
: LGTM! Installation setup follows Windows conventions.
Good practices implemented:
- Proper Program Files installation path
- Architecture-specific installer naming
- Visible installation details for troubleshooting
78-81
: LGTM! Proper architecture validation.
The architecture check in .onInit prevents installation of wrong architecture builds.
51-68
: Consider adding EULA for file association feature.
Since this installer handles file associations which integrate deeply with the Windows system, consider uncommenting and implementing the EULA page to inform users about:
- File types being associated
- System integration implications
- Usage terms and conditions
v3/internal/commands/build-assets.go (4)
26-26
: LGTM! Improved field naming.
The rename from Binary
to BinaryName
makes the field's purpose more explicit and self-documenting.
84-88
: LGTM! Proper platform-specific binary naming.
The code correctly handles Windows-specific .exe
extension while maintaining platform independence for other OS.
91-92
: LGTM! Clean config initialization and extraction.
The configuration handling is well-structured with proper error checking.
Also applies to: 101-109
160-162
: LGTM! Clean config update and extraction.
The configuration update and extraction process is well-structured.
v3/pkg/application/application_darwin_delegate.m (1)
14-15
: Verify memory management of UTF8String conversion.
The UTF8String
method returns a C string that's valid only as long as the NSString exists. Since we're passing this to an external function, we should ensure proper memory handling.
✅ Verification successful
Memory management is correctly handled in this case
The implementation is safe because:
- The
HandleOpenFile
Go function immediately converts the C string to a Go string usingC.GoString()
, which creates a copy of the data - The original NSString and its UTF8String remain valid throughout the Objective-C method call
- The conversion and handling happen synchronously within the scope of the
application:openFile:
method
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for HandleOpenFile implementation to verify string handling
ast-grep --pattern 'void HandleOpenFile(char* filename) {
$$$
}'
Length of output: 68
Script:
#!/bin/bash
# Search for HandleOpenFile function declaration and implementation using ripgrep
rg -l "HandleOpenFile" --type cpp --type c --type objc
# Then get the content of files containing HandleOpenFile
rg "HandleOpenFile" -B 3 -A 10 --type cpp --type c --type objc
Length of output: 3966
Script:
#!/bin/bash
# Let's search for the actual implementation of HandleOpenFile in C/C++ files
# since we only found declarations and calls so far
rg -g '*.{c,cpp}' "HandleOpenFile" -B 3 -A 10
# Also search for any Go files that might implement this function
# since it appears to be a bridge between Objective-C and another language
rg -g '*.go' "HandleOpenFile" -B 3 -A 10
Length of output: 2096
v3/internal/commands/updatable_build_assets/nsis/wails_tools.nsh.tmpl (1)
204-210
: Validate icon files and use absolute paths.
The current implementation has potential issues:
- No validation that icon files exist.
- Uses relative path "../" which could be unreliable.
Let's verify the icon file handling in the codebase:
v3/examples/file-association/build/nsis/wails_tools.nsh (3)
58-98
: LGTM! Robust architecture validation.
The architecture check macro implements comprehensive validation with proper error handling for both silent and interactive installations.
114-135
: LGTM! Comprehensive uninstaller setup.
The uninstaller management follows Windows best practices with proper registry handling and cleanup.
145-179
: Verify WebView2 bootstrapper integrity.
Consider adding checksum verification for the WebView2 bootstrapper to ensure its integrity.
v3/pkg/application/application_darwin.go (1)
374-377
: Verify event handling setup.
The event emission looks correct, but we should verify:
- The
events.Common.ApplicationOpenedWithFile
event type is registered - Event consumers are properly set up to handle this event
Let's verify the event setup:
✅ Verification successful
Let me gather more information to verify the event type definition since it wasn't found in the previous search.
Event handling is properly set up and integrated
The verification shows:
- The event type
ApplicationOpenedWithFile
is properly registered inv3/pkg/events/events.go
with ID 1206 - Event consumers are correctly set up as demonstrated in the file association examples
- The event is properly documented in the guides and API documentation
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify event registration and handling
# Test 1: Check if the event type is defined
rg -A 2 "ApplicationOpenedWithFile.*="
# Test 2: Check for event handlers
rg -A 5 "OnApplicationEvent.*ApplicationOpenedWithFile"
Length of output: 1825
Script:
#!/bin/bash
# Search for ApplicationOpenedWithFile in events package
rg -A 2 "ApplicationOpenedWithFile" v3/pkg/events/
# Search for event type registration in Common
ast-grep --pattern 'type Common struct {
$$$
ApplicationOpenedWithFile $_
$$$
}'
Length of output: 534
v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.js (2)
192-192
: Verify consistent implementation across platforms.
Since this is a common event, ensure it's properly implemented and emitted on all supported platforms (Windows, macOS, Linux).
Let's check the implementation across platforms:
#!/bin/bash
# Description: Verify consistent implementation across platforms
# Expected: Implementation should exist for each platform
# Search for ApplicationOpenedWithFile usage in platform-specific files
echo "=== Windows Implementation ==="
rg "ApplicationOpenedWithFile" "**/*_windows.go"
echo "=== macOS Implementation ==="
rg "ApplicationOpenedWithFile" "**/*_darwin.go"
echo "=== Linux Implementation ==="
rg "ApplicationOpenedWithFile" "**/*_linux.go"
192-192
: LGTM! Verify documentation coverage.
The new ApplicationOpenedWithFile
event follows the established naming convention and is appropriately placed in the Common section for cross-platform support.
Let's verify the documentation coverage:
✅ Verification successful
Documentation coverage for ApplicationOpenedWithFile
event is complete
The ApplicationOpenedWithFile
event is well documented in both the file associations guide and example implementation:
- Comprehensive documentation in
mkdocs-website/docs/en/learn/guides/file-associations.md
- Working example in
v3/examples/file-association/main.go
- Additional notes about dialog handling in
mkdocs-website/docs/en/API/application_dialogs.md
The documentation covers:
- Event usage and implementation
- Configuration requirements
- Platform-specific considerations
- Best practices for handling the event
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if the new event is properly documented
# Expected: Documentation should exist for the ApplicationOpenedWithFile event
# Search in markdown documentation
rg -i "ApplicationOpenedWithFile" "docs/"
# Search in API documentation
rg -i "ApplicationOpenedWithFile" "**/*.md"
Length of output: 513
Script:
#!/bin/bash
# Let's try a broader search for documentation and implementation
# First, find all potential documentation files
echo "=== Documentation files ==="
fd -e md
# Then search for the event in all files
echo -e "\n=== Implementation search ==="
rg -l "ApplicationOpenedWithFile"
# Look for any Go files that might contain the implementation
echo -e "\n=== Go files with 'file' related functionality ==="
fd -e go | grep -i "file"
Length of output: 8704
Script:
#!/bin/bash
# Let's check the content of the file associations documentation and implementation
echo "=== File Associations Documentation ==="
cat "mkdocs-website/docs/en/learn/guides/file-associations.md"
echo -e "\n=== Event Documentation ==="
cat "mkdocs-website/docs/en/API/application_dialogs.md"
echo -e "\n=== Example Implementation ==="
cat "v3/examples/file-association/main.go"
Length of output: 11087
v3/pkg/application/application_windows.go (2)
7-9
: LGTM: Imports are appropriate for file association handling.
The new imports are necessary and well-organized, supporting the file association feature implementation.
141-156
: Verify the impact on the application startup time.
The file existence check might impact the application's startup performance. Consider:
- Making the file validation asynchronous
- Adding a timeout for the file check
v3/pkg/application/dialogs_darwin.go (1)
22-36
: Verify main thread execution for NSAlert operations
The removal of dispatch_async
block assumes that this code is already running on the main thread. While this might be true due to the InvokeAsync
wrapper in Go code, it's crucial to ensure thread safety as UI operations in Cocoa must run on the main thread.
Let's verify the execution context:
Consider adding a runtime assertion to verify main thread execution:
static void showAboutBox(char* title, char *message, void *icon, int length) {
+ // Assert main thread
+ NSCAssert([NSThread isMainThread], @"showAboutBox must be called on main thread");
NSAlert *alert = [[NSAlert alloc] init];
// ... rest of the implementation
}
✅ Verification successful
Let me gather more information about the main thread dispatch mechanism.
Based on the gathered information, I can now provide the final response:
Thread safety is properly handled for NSAlert operations
The code is safe as it's already running on the main thread through the InvokeAsync
wrapper, which internally uses dispatchOnMainThread
. The implementation in mainthread_darwin.go
shows that dispatchOnMainThread
uses dispatch_async(dispatch_get_main_queue(), ...)
to ensure UI operations run on the main thread. The removal of the explicit dispatch_async
block is correct as it would be redundant.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for InvokeAsync implementation to confirm main thread dispatch
rg -A 5 "func InvokeAsync"
# Search for other NSAlert usages to compare thread handling
rg "NSAlert" --type c
Length of output: 459
Script:
#!/bin/bash
# Check the implementation of dispatchOnMainThread
rg -A 10 "dispatchOnMainThread"
# Look for the globalApplication definition and initialization
rg "globalApplication"
# Check if there are any other dialog-related functions that might show thread handling patterns
rg "showDialog|showMessage|alert" --type go
Length of output: 45532
mkdocs-website/docs/en/changelog.md (1)
24-24
: LGTM! Entry correctly documents the file association feature.
The changelog entry properly documents the addition of File Association support, correctly attributing it to PR #3873. This aligns with the PR objectives of porting the file association feature from v2 to v3.
v3/pkg/events/events.go (6)
32-32
: LGTM: New event type for file association support.
The addition of ApplicationOpenedWithFile
event type is well-integrated into the common events, following the existing patterns and maintaining sequential event ID numbering.
Also applies to: 60-60
68-73
: LGTM: Consistent formatting in Linux events.
The formatting changes align with the codebase's style, improving readability.
Also applies to: 80-85
221-344
: LGTM: Consistent formatting in Mac events.
The formatting changes maintain consistency across the large set of Mac-specific events while preserving the event ID sequence.
359-377
: LGTM: Consistent formatting in Windows events.
The formatting changes align with the codebase's style while maintaining proper event ID sequencing.
Also applies to: 382-408
599-599
: LGTM: Event mapping for file association support.
The new event mapping follows the established pattern and correctly uses the "common" namespace for cross-platform functionality.
32-32
: Verify event handling implementation.
Let's verify the implementation of the ApplicationOpenedWithFile
event handler in the application files:
Also applies to: 599-599
✅ Verification successful
Event handling implementation is properly implemented across platforms
The ApplicationOpenedWithFile
event is correctly implemented:
- Windows: Handled in
application_windows.go
through the main event loop - macOS: Implemented via
HandleOpenFile
inapplication_darwin.go
- Example usage demonstrated in
file-association/main.go
showing proper event subscription and handling
The implementation follows consistent patterns across platforms and properly emits events with the required context.
[platform_specific][event_handling]
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for ApplicationOpenedWithFile event handler implementation
echo "Searching for event handler implementation..."
rg -l "ApplicationOpenedWithFile" --type go
# Search for file association related code
echo "Searching for file association related code..."
rg -l "HandleOpenFile|file\s+association" --type go
Length of output: 534
Script:
#!/bin/bash
# Let's examine the implementation details in the found files
echo "Checking v3/examples/file-association/main.go..."
rg "ApplicationOpenedWithFile" -B 5 -A 10 v3/examples/file-association/main.go
echo -e "\nChecking v3/pkg/application/application_windows.go..."
rg "ApplicationOpenedWithFile" -B 5 -A 10 v3/pkg/application/application_windows.go
echo -e "\nChecking v3/pkg/application/application_darwin.go..."
rg "ApplicationOpenedWithFile" -B 5 -A 10 v3/pkg/application/application_darwin.go
echo -e "\nChecking file association handling in application_darwin.go..."
rg "HandleOpenFile" -B 5 -A 10 v3/pkg/application/application_darwin.go
Length of output: 2350
v3/pkg/application/webview_window_windows.go (2)
383-384
: LGTM: Improved visibility handling architecture
The change from w.show()
to w.parent.Show()
is a good architectural improvement that better encapsulates window visibility control at the parent level. This allows the parent window to handle any necessary initialization (like file association) before displaying the window.
Line range hint 1066-1084
: Verify file drag & drop security measures
While the drag & drop implementation looks solid, consider adding additional validation for dropped files to prevent potential security risks:
- File size limits
- File type validation
- Path traversal checks
v3/tasks/events/generate.go (1)
5-6
: New imports are appropriate for version handling and JSON parsing
The addition of semver
and gjson
packages is necessary for version management and JSON parsing functionalities introduced in the code.
const resultElement = document.getElementById('result'); | ||
const timeElement = document.getElementById('time'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add null checks for DOM elements
The code assumes these elements exist in the DOM. Consider adding null checks to prevent runtime errors.
-const resultElement = document.getElementById('result');
-const timeElement = document.getElementById('time');
+const resultElement = document.getElementById('result');
+const timeElement = document.getElementById('time');
+
+if (!resultElement || !timeElement) {
+ console.error('Required DOM elements not found');
+}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const resultElement = document.getElementById('result'); | |
const timeElement = document.getElementById('time'); | |
const resultElement = document.getElementById('result'); | |
const timeElement = document.getElementById('time'); | |
if (!resultElement || !timeElement) { | |
console.error('Required DOM elements not found'); | |
} |
Events.On('time', (time) => { | ||
timeElement.innerText = time.data; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add file association event handling
This example should demonstrate file association functionality as per PR objectives. Consider:
- Add event listeners for file open events
- Implement cleanup for event listeners
- Add error handling for event data
+// Handle file open events
+Events.On('wails:application:file-open', (event) => {
+ console.log('File opened:', event.data);
+ // Handle the opened file
+});
+
Events.On('time', (time) => {
timeElement.innerText = time.data;
});
+
+// Cleanup function
+function cleanup() {
+ Events.Off('time');
+ Events.Off('wails:application:file-open');
+}
+
+// Register cleanup
+window.addEventListener('unload', cleanup);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
Events.On('time', (time) => { | |
timeElement.innerText = time.data; | |
}); | |
// Handle file open events | |
Events.On('wails:application:file-open', (event) => { | |
console.log('File opened:', event.data); | |
// Handle the opened file | |
}); | |
Events.On('time', (time) => { | |
timeElement.innerText = time.data; | |
}); | |
// Cleanup function | |
function cleanup() { | |
Events.Off('time'); | |
Events.Off('wails:application:file-open'); | |
} | |
// Register cleanup | |
window.addEventListener('unload', cleanup); |
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding task dependencies and error handling.
The execute commands look well-structured, but consider these improvements:
- Frontend tasks might fail if Node.js is not installed
go mod tidy
might need to run before frontend tasks if there are Go package dependencies
Consider adding pre-flight checks:
executes:
+ - cmd: command -v node >/dev/null 2>&1 || { echo "Node.js is required but not installed."; exit 1; }
+ type: blocking
- cmd: wails3 task common:install:frontend:deps
type: once
Committable suggestion skipped: line range outside the PR's diff.
# Define variables | ||
APP_DIR="${APP_NAME}.AppDir" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add validation for required environment variables.
The script assumes environment variables (APP_NAME, APP_BINARY, ICON_PATH, DESKTOP_FILE) are set but doesn't validate their existence. This could lead to unclear errors later.
Add this validation at the beginning of the script:
# Define variables
+# Validate required environment variables
+for var in APP_NAME APP_BINARY ICON_PATH DESKTOP_FILE; do
+ if [ -z "${!var}" ]; then
+ echo "Error: $var environment variable is not set"
+ exit 1
+ fi
+done
+
APP_DIR="${APP_NAME}.AppDir"
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
# Define variables | |
APP_DIR="${APP_NAME}.AppDir" | |
# Define variables | |
# Validate required environment variables | |
for var in APP_NAME APP_BINARY ICON_PATH DESKTOP_FILE; do | |
if [ -z "${!var}" ]; then | |
echo "Error: $var environment variable is not set" | |
exit 1 | |
fi | |
done | |
APP_DIR="${APP_NAME}.AppDir" |
# 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enhance download security and reliability.
The script downloads LinuxDeploy without verifying its integrity or handling timeouts. This could be a security risk and might fail in unstable networks.
Consider these improvements:
# Download linuxdeploy and make it executable
-wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
+LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
+LINUXDEPLOY_SHA256="<known-checksum>" # Replace with actual checksum
+
+if ! wget --timeout=15 --tries=3 -q -4 -N "$LINUXDEPLOY_URL"; then
+ echo "Error: Failed to download LinuxDeploy"
+ exit 1
+fi
+
+echo "$LINUXDEPLOY_SHA256 linuxdeploy-x86_64.AppImage" | sha256sum -c || {
+ echo "Error: LinuxDeploy checksum verification failed"
+ rm -f linuxdeploy-x86_64.AppImage
+ exit 1
+}
+
chmod +x linuxdeploy-x86_64.AppImage
+
+# Clean up
+trap 'rm -f linuxdeploy-x86_64.AppImage' EXIT
Committable suggestion skipped: line range outside the PR's diff.
//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, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add input validation and documentation.
The function needs input validation and documentation to improve robustness and maintainability:
- Add input validation for the filePath parameter
- Add documentation explaining the function's purpose and usage
Apply this diff:
+// HandleOpenFile is called by the Objective-C runtime when a file is opened with the application.
+// It converts the C string file path to Go string and emits an ApplicationOpenedWithFile event.
//export HandleOpenFile
func HandleOpenFile(filePath *C.char) {
+ if filePath == nil {
+ return
+ }
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,
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
//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, | |
} | |
} | |
// HandleOpenFile is called by the Objective-C runtime when a file is opened with the application. | |
// It converts the C string file path to Go string and emits an ApplicationOpenedWithFile event. | |
//export HandleOpenFile | |
func HandleOpenFile(filePath *C.char) { | |
if filePath == nil { | |
return | |
} | |
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, | |
} | |
} |
if len(os.Args) == 2 { | ||
arg := os.Args[1] | ||
ext := filepath.Ext(arg) | ||
println("Got extension: ", ext) | ||
if slices.Contains(m.parent.options.FileAssociations, ext) { | ||
println("Slices contains") | ||
eventContext := newApplicationEventContext() | ||
eventContext.setOpenedWithFile(arg) | ||
// EmitEvent application started event | ||
println("sending event") | ||
applicationEvents <- &ApplicationEvent{ | ||
Id: uint(events.Common.ApplicationOpenedWithFile), | ||
ctx: eventContext, | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add file path validation and improve error handling.
The current implementation has several potential issues:
- No validation if the argument is actually a file path
- No error handling for filepath.Ext
- No verification if the file exists
Consider this improved implementation:
if len(os.Args) == 2 {
arg := os.Args[1]
- ext := filepath.Ext(arg)
- println("Got extension: ", ext)
- if slices.Contains(m.parent.options.FileAssociations, ext) {
- println("Slices contains")
- eventContext := newApplicationEventContext()
- eventContext.setOpenedWithFile(arg)
- // EmitEvent application started event
- println("sending event")
- applicationEvents <- &ApplicationEvent{
- Id: uint(events.Common.ApplicationOpenedWithFile),
- ctx: eventContext,
- }
- }
+ // Verify if the argument is a valid file
+ if fileInfo, err := os.Stat(arg); err == nil && !fileInfo.IsDir() {
+ ext := filepath.Ext(arg)
+ if slices.Contains(m.parent.options.FileAssociations, ext) {
+ eventContext := newApplicationEventContext()
+ eventContext.setOpenedWithFile(arg)
+ applicationEvents <- &ApplicationEvent{
+ Id: uint(events.Common.ApplicationOpenedWithFile),
+ ctx: eventContext,
+ }
+ }
+ }
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if len(os.Args) == 2 { | |
arg := os.Args[1] | |
ext := filepath.Ext(arg) | |
println("Got extension: ", ext) | |
if slices.Contains(m.parent.options.FileAssociations, ext) { | |
println("Slices contains") | |
eventContext := newApplicationEventContext() | |
eventContext.setOpenedWithFile(arg) | |
// EmitEvent application started event | |
println("sending event") | |
applicationEvents <- &ApplicationEvent{ | |
Id: uint(events.Common.ApplicationOpenedWithFile), | |
ctx: eventContext, | |
} | |
} | |
} | |
if len(os.Args) == 2 { | |
arg := os.Args[1] | |
// Verify if the argument is a valid file | |
if fileInfo, err := os.Stat(arg); err == nil && !fileInfo.IsDir() { | |
ext := filepath.Ext(arg) | |
if slices.Contains(m.parent.options.FileAssociations, ext) { | |
eventContext := newApplicationEventContext() | |
eventContext.setOpenedWithFile(arg) | |
applicationEvents <- &ApplicationEvent{ | |
Id: uint(events.Common.ApplicationOpenedWithFile), | |
ctx: eventContext, | |
} | |
} | |
} | |
} |
panic(err) | ||
} | ||
|
||
err = os.WriteFile(packageJsonFilename, []byte(newJSON), 0644) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check for errors when writing to package.json
The error returned by os.WriteFile
is assigned to err
but not checked. This could lead to silent failures if the file write operation does not succeed.
Apply this diff to handle the error:
err = os.WriteFile(packageJsonFilename, []byte(newJSON), 0644)
+if err != nil {
+ panic(err)
+}
Committable suggestion skipped: line range outside the PR's diff.
version := gjson.Get(string(packageJSON), "version").String() | ||
// Parse and increment version | ||
v := semver.MustParse(version) | ||
prerelease := v.Prerelease() | ||
// Split the prerelease by the "." and increment the last part by 1 | ||
parts := strings.Split(prerelease, ".") | ||
prereleaseDigits, err := strconv.Atoi(parts[len(parts)-1]) | ||
if err != nil { | ||
panic(err) | ||
} | ||
prereleaseNumber := strconv.Itoa(prereleaseDigits + 1) | ||
parts[len(parts)-1] = prereleaseNumber | ||
prerelease = strings.Join(parts, ".") | ||
newVersion, err := v.SetPrerelease(prerelease) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add checks for versions without a prerelease segment to prevent panics
Currently, the code assumes that the version string in package.json
has a prerelease segment. If the version
does not have a prerelease segment, v.Prerelease()
will return an empty string, leading to potential panics due to index out of range or conversion errors.
Apply this diff to handle versions without a prerelease segment:
version := gjson.Get(string(packageJSON), "version").String()
// Parse and increment version
v := semver.MustParse(version)
prerelease := v.Prerelease()
+if prerelease == "" {
+ // Set a default prerelease segment if none exists
+ prerelease = "alpha.0"
+}
// Split the prerelease by the "." and increment the last part by 1
parts := strings.Split(prerelease, ".")
prereleaseDigits, err := strconv.Atoi(parts[len(parts)-1])
if err != nil {
panic(err)
}
Alternatively, ensure that the code handles versions without prerelease segments appropriately.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
version := gjson.Get(string(packageJSON), "version").String() | |
// Parse and increment version | |
v := semver.MustParse(version) | |
prerelease := v.Prerelease() | |
// Split the prerelease by the "." and increment the last part by 1 | |
parts := strings.Split(prerelease, ".") | |
prereleaseDigits, err := strconv.Atoi(parts[len(parts)-1]) | |
if err != nil { | |
panic(err) | |
} | |
prereleaseNumber := strconv.Itoa(prereleaseDigits + 1) | |
parts[len(parts)-1] = prereleaseNumber | |
prerelease = strings.Join(parts, ".") | |
newVersion, err := v.SetPrerelease(prerelease) | |
if err != nil { | |
panic(err) | |
} | |
version := gjson.Get(string(packageJSON), "version").String() | |
// Parse and increment version | |
v := semver.MustParse(version) | |
prerelease := v.Prerelease() | |
if prerelease == "" { | |
// Set a default prerelease segment if none exists | |
prerelease = "alpha.0" | |
} | |
// Split the prerelease by the "." and increment the last part by 1 | |
parts := strings.Split(prerelease, ".") | |
prereleaseDigits, err := strconv.Atoi(parts[len(parts)-1]) | |
if err != nil { | |
panic(err) | |
} | |
prereleaseNumber := strconv.Itoa(prereleaseDigits + 1) | |
parts[len(parts)-1] = prereleaseNumber | |
prerelease = strings.Join(parts, ".") | |
newVersion, err := v.SetPrerelease(prerelease) | |
if err != nil { | |
panic(err) | |
} |
v := semver.MustParse(version) | ||
prerelease := v.Prerelease() | ||
// Split the prerelease by the "." and increment the last part by 1 | ||
parts := strings.Split(prerelease, ".") | ||
prereleaseDigits, err := strconv.Atoi(parts[len(parts)-1]) | ||
if err != nil { | ||
panic(err) | ||
} | ||
prereleaseNumber := strconv.Itoa(prereleaseDigits + 1) | ||
parts[len(parts)-1] = prereleaseNumber | ||
prerelease = strings.Join(parts, ".") | ||
newVersion, err := v.SetPrerelease(prerelease) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Simplify prerelease version increment using semver's built-in methods
Instead of manually parsing and incrementing the prerelease segment, you can use the semver library's IncPrerelease()
method for a more concise and less error-prone implementation.
Apply this diff to simplify the version increment:
version := gjson.Get(string(packageJSON), "version").String()
// Parse and increment version
v := semver.MustParse(version)
-// Existing code manually increments the prerelease segment
+// Increment the prerelease version using semver
+newVersion := v.IncPrerelease()
This approach reduces complexity and leverages the semver library's capabilities.
Committable suggestion skipped: line range outside the PR's diff.
Quality Gate passedIssues Measures |
* Update nsis template * Move app data into config.yml * mac support * Add FileAssociations application config option Support `ApplicationOpenedWithFile` event on Windows Add docs * Add FileAssociations application config option Support `ApplicationOpenedWithFile` event on Windows Add docs Add test project * Update example & docs. Fix show window bug. * Fix window show event bug * Update changelog
Adds support for File Association with your Wails application.
Fixes #3655
Summary by CodeRabbit
Release Notes
New Features
ApplicationOpenedWithFile
to enhance file handling capabilities.Bug Fixes
Documentation
Improvements