/
explorer_macos.go
135 lines (109 loc) · 2.63 KB
/
explorer_macos.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//go:build darwin && !ios
// +build darwin,!ios
package gexplorer
/*
#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
#import <Appkit/AppKit.h>
// Defined on explorer_macos.m file.
extern void exportFile(CFTypeRef viewRef, int32_t id, char * name);
extern void importFile(CFTypeRef viewRef, int32_t id, char * ext);
extern void importFiles(CFTypeRef viewRef, int32_t id, char * ext);
*/
import "C"
import (
"net/url"
"strings"
"unsafe"
)
type explorer struct {
run RunHandler
view C.CFTypeRef
result chan result
}
func newExplorer(run RunHandler) *explorer {
return &explorer{
run: run,
result: make(chan result),
}
}
func (e *Explorer) setView(v uintptr) {
e.view = C.CFTypeRef(v)
}
func (e *Explorer) importFile(extensions ...string) (string, error) {
for i, ext := range extensions {
extensions[i] = strings.TrimPrefix(ext, ".")
}
cextensions := C.CString(strings.Join(extensions, ","))
e.run(func() {
C.importFile(e.view, C.int32_t(e.id), cextensions)
})
resp := <-e.result
if resp.error != nil {
return "", resp.error
}
return resp.filenames[0], nil
}
func (e *Explorer) importFiles(extensions ...string) ([]string, error) {
for i, ext := range extensions {
extensions[i] = strings.TrimPrefix(ext, ".")
}
cextensions := C.CString(strings.Join(extensions, ","))
e.run(func() {
C.importFiles(e.view, C.int32_t(e.id), cextensions)
})
resp := <-e.result
if resp.error != nil {
return nil, resp.error
}
return resp.filenames, nil
}
func (e *Explorer) exportFile(name string) (string, error) {
cname := C.CString(name)
e.run(func() {
C.exportFile(e.view, C.int32_t(e.id), cname)
})
resp := <-e.result
if resp.error != nil {
return "", resp.error
}
return resp.filenames[0], nil
}
//export importCallback
func importCallback(id int32, u *C.char) {
if v, ok := active.Load(id); ok {
v.(*explorer).result <- newPath([]*C.char{u})
}
}
//export importsCallback
func importsCallback(id int32, count int32, u **C.char) {
if v, ok := active.Load(id); ok {
v.(*explorer).result <- newPath(unsafe.Slice(u, count))
}
}
//export exportCallback
func exportCallback(id int32, u *C.char) {
if v, ok := active.Load(id); ok {
v.(*explorer).result <- newPath([]*C.char{u})
}
}
func newPath(urls []*C.char) result {
res := result{
filenames: make([]string, len(urls)),
}
for i, u := range urls {
name := C.GoString(u)
if name == "" {
return result{error: ErrUserDecline}
}
uri, err := url.Parse(name)
if err != nil {
return result{error: err}
}
path, err := url.PathUnescape(uri.Path)
if err != nil {
return result{error: err}
}
res.filenames[i] = path
}
return res
}