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-22 06:44:38 +11:00
committed by GitHub
co-authored by Lea Anthony
parent 42708e7f40
commit 6c46f6b41c
13 changed files with 493 additions and 62 deletions
@@ -11,7 +11,7 @@
#import <Cocoa/Cocoa.h>
#import "WailsContext.h"
@interface AppDelegate : NSResponder <NSTouchBarProvider>
@interface AppDelegate : NSResponder <NSApplicationDelegate, NSTouchBarProvider>
@property bool alwaysOnTop;
@property bool startHidden;
@@ -20,4 +20,6 @@
@end
extern void HandleOpenFile(char *);
#endif /* AppDelegate_h */
@@ -11,9 +11,17 @@
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return NO;
-(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename
{
const char* utf8FileName = filename.UTF8String;
HandleOpenFile((char*)utf8FileName);
return YES;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return NO;
}
- (void)applicationWillFinishLaunching:(NSNotification *)aNotification {
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
if (self.alwaysOnTop) {
@@ -38,6 +38,7 @@ const startURL = "wails://wails/"
var messageBuffer = make(chan string, 100)
var requestBuffer = make(chan webview.Request, 100)
var callbackBuffer = make(chan uint, 10)
var openFilepathBuffer = make(chan string, 100)
type Frontend struct {
@@ -107,15 +108,23 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger.
go result.startMessageProcessor()
go result.startCallbackProcessor()
go result.startFileOpenProcessor()
return result
}
func (f *Frontend) startFileOpenProcessor() {
for filePath := range openFilepathBuffer {
f.ProcessOpenFileEvent(filePath)
}
}
func (f *Frontend) startMessageProcessor() {
for message := range messageBuffer {
f.processMessage(message)
}
}
func (f *Frontend) startRequestProcessor() {
for request := range requestBuffer {
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) {
escaped, err := json.Marshal(message)
if err != nil {
@@ -398,3 +413,9 @@ func processCallback(callbackID uint) {
func processURLRequest(_ unsafe.Pointer, wkURLSchemeTask unsafe.Pointer) {
requestBuffer <- webview.NewRequest(wkURLSchemeTask)
}
//export HandleOpenFile
func HandleOpenFile(filePath *C.char) {
goFilepath := C.GoString(filePath)
openFilepathBuffer <- goFilepath
}
+14 -5
View File
@@ -216,11 +216,20 @@ type Author struct {
}
type Info struct {
CompanyName string `json:"companyName"`
ProductName string `json:"productName"`
ProductVersion string `json:"productVersion"`
Copyright *string `json:"copyright"`
Comments *string `json:"comments"`
CompanyName string `json:"companyName"`
ProductName string `json:"productName"`
ProductVersion string `json:"productVersion"`
Copyright *string `json:"copyright"`
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 {