5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-03 03:52:41 +08:00

Implement file association Open a file from Finder/Explorer (#2918)

* implement MacOS openFile/openFiles events

* wip: windows file association

* fix macro import

* add file icon copy

* try copy icon

* keep only required part of scripts

* update config schema

* fix json

* set fileAssociation for mac via config

* proper iconName handling

* add fileAssociation icon generator

* fix file association icons bundle

* don't break compatibility

* remove mimeType as not supported linux for now

* add documentation

* adjust config schema

* restore formatting

* remove unused option in file association

* get rid of openFiles mac os. change configuration structure

* remove unused channel

* fix documentation

* fix typo

---------

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
Andrey Pshenkin 2023-10-21 20:44:38 +01:00 committed by GitHub
parent 42708e7f40
commit 6c46f6b41c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 493 additions and 62 deletions

View File

@ -11,7 +11,7 @@
#import <Cocoa/Cocoa.h> #import <Cocoa/Cocoa.h>
#import "WailsContext.h" #import "WailsContext.h"
@interface AppDelegate : NSResponder <NSTouchBarProvider> @interface AppDelegate : NSResponder <NSApplicationDelegate, NSTouchBarProvider>
@property bool alwaysOnTop; @property bool alwaysOnTop;
@property bool startHidden; @property bool startHidden;
@ -20,4 +20,6 @@
@end @end
extern void HandleOpenFile(char *);
#endif /* AppDelegate_h */ #endif /* AppDelegate_h */

View File

@ -11,9 +11,17 @@
#import "AppDelegate.h" #import "AppDelegate.h"
@implementation AppDelegate @implementation AppDelegate
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
const char* utf8FileName = filename.UTF8String;
HandleOpenFile((char*)utf8FileName);
return YES;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return NO; return NO;
} }
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification { - (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
if (self.alwaysOnTop) { if (self.alwaysOnTop) {

View File

@ -38,6 +38,7 @@ const startURL = "wails://wails/"
var messageBuffer = make(chan string, 100) var messageBuffer = make(chan string, 100)
var requestBuffer = make(chan webview.Request, 100) var requestBuffer = make(chan webview.Request, 100)
var callbackBuffer = make(chan uint, 10) var callbackBuffer = make(chan uint, 10)
var openFilepathBuffer = make(chan string, 100)
type Frontend struct { type Frontend struct {
@ -107,15 +108,23 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
go result.startMessageProcessor() go result.startMessageProcessor()
go result.startCallbackProcessor() go result.startCallbackProcessor()
go result.startFileOpenProcessor()
return result return result
} }
func (f *Frontend) startFileOpenProcessor() {
for filePath := range openFilepathBuffer {
f.ProcessOpenFileEvent(filePath)
}
}
func (f *Frontend) startMessageProcessor() { func (f *Frontend) startMessageProcessor() {
for message := range messageBuffer { for message := range messageBuffer {
f.processMessage(message) f.processMessage(message)
} }
} }
func (f *Frontend) startRequestProcessor() { func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer { for request := range requestBuffer {
f.assets.ServeWebViewRequest(request) f.assets.ServeWebViewRequest(request)
@ -355,6 +364,12 @@ func (f *Frontend) processMessage(message string) {
} }
func (f *Frontend) ProcessOpenFileEvent(filePath string) {
if f.frontendOptions.Mac != nil && f.frontendOptions.Mac.OnFileOpen != nil {
f.frontendOptions.Mac.OnFileOpen(filePath)
}
}
func (f *Frontend) Callback(message string) { func (f *Frontend) Callback(message string) {
escaped, err := json.Marshal(message) escaped, err := json.Marshal(message)
if err != nil { if err != nil {
@ -398,3 +413,9 @@ func processCallback(callbackID uint) {
func processURLRequest(_ unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) { func processURLRequest(_ unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
requestBuffer <- webview.NewRequest(wkURLSchemeTask) requestBuffer <- webview.NewRequest(wkURLSchemeTask)
} }
//export HandleOpenFile
func HandleOpenFile(filePath *C.char) {
goFilepath := C.GoString(filePath)
openFilepathBuffer <- goFilepath
}

View File

@ -216,11 +216,20 @@ type Author struct {
} }
type Info struct { type Info struct {
CompanyName string `json:"companyName"` CompanyName string `json:"companyName"`
ProductName string `json:"productName"` ProductName string `json:"productName"`
ProductVersion string `json:"productVersion"` ProductVersion string `json:"productVersion"`
Copyright *string `json:"copyright"` Copyright *string `json:"copyright"`
Comments *string `json:"comments"` Comments *string `json:"comments"`
FileAssociations []FileAssociation `json:"fileAssociations"`
}
type FileAssociation struct {
Ext string `json:"ext"`
Name string `json:"name"`
Description string `json:"description"`
IconName string `json:"iconName"`
Role string `json:"role"`
} }
type Bindings struct { type Bindings struct {

View File

@ -23,6 +23,25 @@
<string>true</string> <string>true</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>{{.Info.Copyright}}</string> <string>{{.Info.Copyright}}</string>
{{if .Info.FileAssociations}}
<key>CFBundleDocumentTypes</key>
<array>
{{range .Info.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}}
<key>NSAppTransportSecurity</key> <key>NSAppTransportSecurity</key>
<dict> <dict>
<key>NSAllowsLocalNetworking</key> <key>NSAllowsLocalNetworking</key>

View File

@ -23,5 +23,24 @@
<string>true</string> <string>true</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>{{.Info.Copyright}}</string> <string>{{.Info.Copyright}}</string>
{{if .Info.FileAssociations}}
<key>CFBundleDocumentTypes</key>
<array>
{{range .Info.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}}
</dict> </dict>
</plist> </plist>

View File

@ -91,6 +91,8 @@ Section
CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}"
!insertmacro wails.associateFiles
!insertmacro wails.writeUninstaller !insertmacro wails.writeUninstaller
SectionEnd SectionEnd
@ -104,5 +106,7 @@ Section "uninstall"
Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk"
Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk"
!insertmacro wails.unassociateFiles
!insertmacro wails.deleteUninstaller !insertmacro wails.deleteUninstaller
SectionEnd SectionEnd

View File

@ -177,3 +177,44 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}"
SetDetailsPrint both SetDetailsPrint both
ok: ok:
!macroend !macroend
# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b
!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" ""
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0"
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}"
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open"
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}`
WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}`
!macroend
!macro APP_UNASSOCIATE EXT FILECLASS
; Backup the previously associated file class
ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup`
WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0"
DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}`
!macroend
!macro wails.associateFiles
; Create file associations
{{range .Info.FileAssociations}}
!insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\""
File "..\{{.IconName}}.ico"
{{end}}
!macroend
!macro wails.unassociateFiles
; Delete app associations
{{range .Info.FileAssociations}}
!insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}"
Delete "$INSTDIR\{{.IconName}}.ico"
{{end}}
!macroend

View File

@ -6,6 +6,7 @@ import (
"github.com/leaanthony/winicon" "github.com/leaanthony/winicon"
"github.com/tc-hib/winres" "github.com/tc-hib/winres"
"github.com/tc-hib/winres/version" "github.com/tc-hib/winres/version"
"github.com/wailsapp/wails/v2/internal/project"
"image" "image"
"os" "os"
"path/filepath" "path/filepath"
@ -95,12 +96,20 @@ func packageApplicationForDarwin(options *Options) error {
return err return err
} }
// Generate Icons // Generate App Icon
err = processApplicationIcon(options, resourceDir) err = processDarwinIcon(options.ProjectData, "appicon", resourceDir, "iconfile")
if err != nil { if err != nil {
return err return err
} }
// Generate FileAssociation Icons
for _, fileAssociation := range options.ProjectData.Info.FileAssociations {
err = processDarwinIcon(options.ProjectData, fileAssociation.IconName, resourceDir, "")
if err != nil {
return err
}
}
options.CompiledBinary = packedBinaryPath options.CompiledBinary = packedBinaryPath
return nil return nil
@ -124,8 +133,8 @@ func processPList(options *Options, contentsDirectory string) error {
return os.WriteFile(targetFile, content, 0644) return os.WriteFile(targetFile, content, 0644)
} }
func processApplicationIcon(options *Options, resourceDir string) (err error) { func processDarwinIcon(projectData *project.Project, iconName string, resourceDir string, destIconName string) (err error) {
appIcon, err := buildassets.ReadFile(options.ProjectData, "appicon.png") appIcon, err := buildassets.ReadFile(projectData, iconName+".png")
if err != nil { if err != nil {
return err return err
} }
@ -135,7 +144,11 @@ func processApplicationIcon(options *Options, resourceDir string) (err error) {
return err return err
} }
tgtBundle := filepath.Join(resourceDir, "iconfile.icns") if destIconName == "" {
destIconName = iconName
}
tgtBundle := filepath.Join(resourceDir, destIconName+".icns")
dest, err := os.Create(tgtBundle) dest, err := os.Create(tgtBundle)
if err != nil { if err != nil {
return err return err
@ -151,13 +164,21 @@ func processApplicationIcon(options *Options, resourceDir string) (err error) {
} }
func packageApplicationForWindows(options *Options) error { func packageApplicationForWindows(options *Options) error {
// Generate icon // Generate app icon
var err error var err error
err = generateIcoFile(options) err = generateIcoFile(options, "appicon", "icon")
if err != nil { if err != nil {
return err return err
} }
// Generate FileAssociation Icons
for _, fileAssociation := range options.ProjectData.Info.FileAssociations {
err = generateIcoFile(options, fileAssociation.IconName, "")
if err != nil {
return err
}
}
// Create syso file // Create syso file
err = compileResources(options) err = compileResources(options)
if err != nil { if err != nil {
@ -171,13 +192,18 @@ func packageApplicationForLinux(_ *Options) error {
return nil return nil
} }
func generateIcoFile(options *Options) error { func generateIcoFile(options *Options, iconName string, destIconName string) error {
content, err := buildassets.ReadFile(options.ProjectData, "appicon.png") content, err := buildassets.ReadFile(options.ProjectData, iconName+".png")
if err != nil { if err != nil {
return err return err
} }
if destIconName == "" {
destIconName = iconName
}
// Check ico file exists already // Check ico file exists already
icoFile := buildassets.GetLocalPath(options.ProjectData, "windows/icon.ico") icoFile := buildassets.GetLocalPath(options.ProjectData, "windows/"+destIconName+".ico")
if !fs.FileExists(icoFile) { if !fs.FileExists(icoFile) {
if dir := filepath.Dir(icoFile); !fs.DirExists(dir) { if dir := filepath.Dir(icoFile); !fs.DirExists(dir) {
if err := fs.MkDirs(dir, 0755); err != nil { if err := fs.MkDirs(dir, 0755); err != nil {

View File

@ -22,6 +22,7 @@ type Options struct {
WindowIsTranslucent bool WindowIsTranslucent bool
Preferences *Preferences Preferences *Preferences
//ActivationPolicy ActivationPolicy //ActivationPolicy ActivationPolicy
About *AboutInfo About *AboutInfo
OnFileOpen func(filePath string) `json:"-"`
//URLHandlers map[string]func(string) //URLHandlers map[string]func(string)
} }

View File

@ -0,0 +1,184 @@
# File Association
File association feature allows you to associate specific file types with your app so that when users open those files,
your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application
that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app.
## Set Up File Association:
To set up file association, you need to modify your application's wails.json file.
In "info" section add a "fileAssociations" section specifying the file types your app should be associated with.
For example:
```json
{
"info": {
"fileAssociations": [
{
"ext": "wails",
"name": "Wails",
"description": "Wails Application File",
"iconName": "wailsFileIcon",
"role": "Editor"
},
{
"ext": "jpg",
"name": "JPEG",
"description": "Image File",
"iconName": "jpegFileIcon",
"role": "Editor"
}
]
}
}
```
| Property | Description |
|:------------|:---------------------------------------------------------------------------------------------------------------------------------------------------|
| ext | The extension (minus the leading period). e.g. png |
| name | The name. e.g. PNG File |
| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows |
| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. |
| role | macOS-only. The apps role with respect to the type. Corresponds to CFBundleTypeRole. |
## Platform Specifics:
### macOS
When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example:
```go title="main.go"
func main() {
// Create application with options
err := wails.Run(&options.App{
Title: "wails-open-file",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
Mac: &mac.Options{
OnFileOpen: func(filePaths []string) { println(filestring) },
},
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err.Error())
}
}
```
### Windows
On Windows file association is supported only with NSIS installer. During installation, the installer will create a
registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed
as argument to your app. To handle this you should parse command line arguments in your app. Example:
```go title="main.go"
func main() {
argsWithoutProg := os.Args[1:]
if len(argsWithoutProg) != 0 {
println("launchArgs", argsWithoutProg)
}
}
```
### Linux
Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually.
For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle.
You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app.
1. Create a .desktop file for your app and specify file associations there. Example:
```ini
[Desktop Entry]
Categories=Office
Exec=/usr/bin/wails-open-file %u
Icon=wails-open-file.png
Name=wails-open-file
Terminal=false
Type=Application
MimeType=application/x-wails;application/x-test
```
2. Create mime types file. Example:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-wails">
<comment>Wails Application File</comment>
<glob pattern="*.wails"/>
</mime-type>
</mime-info>
```
3. Create icons for your file types. SVG icons are recommended.
4. Prepare postInstall/postRemove scripts for your package. Example:
```sh
# reload mime types to register file associations
update-mime-database /usr/share/mime
# reload desktop database to load app in list of available
update-desktop-database /usr/share/applications
# update icons
update-icon-caches /usr/share/icons/*
```
5. Configure nfpm to use your scripts and files. Example:
```yaml
name: "wails-open-file"
arch: "arm64"
platform: "linux"
version: "1.0.0"
section: "default"
priority: "extra"
maintainer: "FooBarCorp <FooBarCorp@gmail.com>"
description: "Sample Package"
vendor: "FooBarCorp"
homepage: "http://example.com"
license: "MIT"
contents:
- src: ../bin/wails-open-file
dst: /usr/bin/wails-open-file
- src: ./main.desktop
dst: /usr/share/applications/wails-open-file.desktop
- src: ./application-wails-mime.xml
dst: /usr/share/mime/packages/application-x-wails.xml
- src: ./application-test-mime.xml
dst: /usr/share/mime/packages/application-x-test.xml
- src: ../appicon.svg
dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg
- src: ../wailsFileIcon.svg
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg
- src: ../testFileIcon.svg
dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg
# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme
- src: ../appicon.svg
dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg
- src: ../wailsFileIcon.svg
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg
- src: ../testFileIcon.svg
dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg
scripts:
postinstall: ./postInstall.sh
postremove: ./postRemove.sh
```
6. Build your .deb package using nfpm:
```sh
nfpm pkg --packager deb --target .
```
7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app,
new instance of app is launched and file path is passed as argument to your app.
To handle this you should parse command line arguments in your app. Example:
```go title="main.go"
func main() {
argsWithoutProg := os.Args[1:]
if len(argsWithoutProg) != 0 {
println("launchArgs", argsWithoutProg)
}
}
```
## Limitations:
On Windows and Linux when associated file is opened, new instance of your app is launched.
Currently, Wails doesn't support opening files in already running app. There is plugin for single instance support for v3 in development.

View File

@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added support for enabling/disabling swipe gestures for Windows WebView2. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2878) - Added support for enabling/disabling swipe gestures for Windows WebView2. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2878)
- When building with `-devtools` flag, CMD/CTRL+SHIFT+F12 can be used to open the devtools. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2915) - When building with `-devtools` flag, CMD/CTRL+SHIFT+F12 can be used to open the devtools. Added by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/2915)
Added file association support for macOS and Windows. Added by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/2918)
- Added support for setting some of the Webview preferences, `textInteractionEnabled` and `tabFocusesLinks` on Mac. Added by @fkhadra in [PR](https://github.com/wailsapp/wails/pull/2937) - Added support for setting some of the Webview preferences, `textInteractionEnabled` and `tabFocusesLinks` on Mac. Added by @fkhadra in [PR](https://github.com/wailsapp/wails/pull/2937)
- Added support for enabling/disabling fullscreen of the Webview on Mac. Added by @fkhadra in [PR](https://github.com/wailsapp/wails/pull/2953) - Added support for enabling/disabling fullscreen of the Webview on Mac. Added by @fkhadra in [PR](https://github.com/wailsapp/wails/pull/2953)
- Added French README.fr.md page. Added by @nejos97 in [PR](https://github.com/wailsapp/wails/pull/2943) - Added French README.fr.md page. Added by @nejos97 in [PR](https://github.com/wailsapp/wails/pull/2943)

View File

@ -72,10 +72,17 @@
"frontend:dev:serverUrl": { "frontend:dev:serverUrl": {
"type": "string", "type": "string",
"description": "URL to a 3rd party dev server to be used to serve assets (eg. Vite). If this is set to 'auto', then the devServerUrl will be inferred from the Vite output", "description": "URL to a 3rd party dev server to be used to serve assets (eg. Vite). If this is set to 'auto', then the devServerUrl will be inferred from the Vite output",
"examples": [ "auto", "http://localhost:3000" ], "examples": [
"auto",
"http://localhost:3000"
],
"oneOf": [ "oneOf": [
{ "format": "uri" }, {
{ "const": "auto" } "format": "uri"
},
{
"const": "auto"
}
] ]
}, },
"wailsjsdir": { "wailsjsdir": {
@ -87,7 +94,9 @@
"version": { "version": {
"description": "Project config version", "description": "Project config version",
"default": "2", "default": "2",
"enum": [ "2" ] "enum": [
"2"
]
}, },
"outputfilename": { "outputfilename": {
"type": "string", "type": "string",
@ -123,7 +132,9 @@
"type": "object", "type": "object",
"description": "The application author", "description": "The application author",
"properties": { "properties": {
"name": { "type": "string" }, "name": {
"type": "string"
},
"email": { "email": {
"type": "string", "type": "string",
"format": "email" "format": "email"
@ -156,6 +167,39 @@
"type": "string", "type": "string",
"description": "A short comment for the app", "description": "A short comment for the app",
"default": "Built using Wails (https://wails.io)" "default": "Built using Wails (https://wails.io)"
},
"fileAssociations": {
"type": "array",
"description": "File associations for the app",
"items": {
"type": "object",
"properties": {
"ext": {
"type": "string",
"description": "The extension (minus the leading period). e.g. png"
},
"name": {
"type": "string",
"description": "The name. e.g. PNG File"
},
"description": {
"type": "string",
"description": "Windows-only. The description. It is displayed on the `Type` column on Windows Explorer."
},
"iconName": {
"type": "string",
"description": "The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows)"
},
"role": {
"description": "macOS-only. The apps role with respect to the type. Corresponds to CFBundleTypeRole.",
"allOf": [
{
"$ref": "#/definitions/BundleTypeRole"
}
]
}
}
}
} }
} }
}, },
@ -185,7 +229,9 @@
} }
}, },
"dependencies": { "dependencies": {
"garbleargs": ["obfuscated"] "garbleargs": [
"obfuscated"
]
}, },
"definitions": { "definitions": {
"OsHook": { "OsHook": {
@ -203,11 +249,21 @@
"description": "Build hooks for different targets.", "description": "Build hooks for different targets.",
"additionalProperties": false, "additionalProperties": false,
"properties": { "properties": {
"{GOOS}/{GOARCH}": { "$ref": "#/definitions/OsArchHook" }, "{GOOS}/{GOARCH}": {
"{GOOS}/*": { "$ref": "#/definitions/OsHook" }, "$ref": "#/definitions/OsArchHook"
"windows/*": { "$ref": "#/definitions/OsHook" }, },
"linux/*": { "$ref": "#/definitions/OsHook" }, "{GOOS}/*": {
"darwin/*": { "$ref": "#/definitions/OsHook" }, "$ref": "#/definitions/OsHook"
},
"windows/*": {
"$ref": "#/definitions/OsHook"
},
"linux/*": {
"$ref": "#/definitions/OsHook"
},
"darwin/*": {
"$ref": "#/definitions/OsHook"
},
"*/*": { "*/*": {
"type": "string", "type": "string",
"description": "Executed at build level before/after a build" "description": "Executed at build level before/after a build"
@ -225,26 +281,66 @@
"description": "Executed at build level before/after a build of the specific platform" "description": "Executed at build level before/after a build of the specific platform"
} }
} }
},
"BundleTypeRole": {
"description": "macOS-only. Corresponds to CFBundleTypeRole",
"oneOf": [
{
"description": "CFBundleTypeRole.Editor. Files can be read and edited.",
"type": "string",
"enum": [
"Editor"
]
},
{
"description": "CFBundleTypeRole.Viewer. Files can be read.",
"type": "string",
"enum": [
"Viewer"
]
},
{
"description": "CFBundleTypeRole.Shell",
"type": "string",
"enum": [
"Shell"
]
},
{
"description": "CFBundleTypeRole.QLGenerator",
"type": "string",
"enum": [
"QLGenerator"
]
},
{
"description": "CFBundleTypeRole.None",
"type": "string",
"enum": [
"None"
]
}
]
} }
}, },
"bindings": { "bindings": {
"type": "object", "type": "object",
"description": "Bindings configurations", "description": "Bindings configurations",
"properties": { "properties": {
"ts_generation": { "ts_generation": {
"type": "object", "type": "object",
"description": "model.ts file generation config", "description": "model.ts file generation config",
"properties": { "properties": {
"prefix": { "prefix": {
"type": "string", "type": "string",
"description": "All generated JavaScript entities will be prefixed with this value" "description": "All generated JavaScript entities will be prefixed with this value"
}, },
"suffix": { "suffix": {
"type": "string", "type": "string",
"description": "All generated JavaScript entities will be suffixed with this value" "description": "All generated JavaScript entities will be suffixed with this value"
} }
} }
} }
} }
} }
} }