@@ 227,70 227,52 @@ func makeFilter(extensions []string) dbus.Variant {
return dbus.MakeVariantWithSignature(filter, dbus.ParseSignatureMust("a(sa(us))"))
}
+type configOpen struct {
+ label string
+ extensions []string
+ multi bool
+ dir bool
+}
+
// importFile opens a file picker to choose a file.
func (e *Explorer) importFile(extensions ...string) (io.ReadCloser, error) {
- var filepath string
- if err := e.withDesktopPortal(func(conn *dbus.Conn, desktopPortal dbus.BusObject, config config) error {
- // Invoke the OpenFile method.
- requestHandle := ""
- options := map[string]dbus.Variant{
- "handle_token": dbus.MakeVariant(config.handleToken),
- }
- if len(extensions) > 0 {
- options["filters"] = makeFilter(extensions)
- }
- err := desktopPortal.Call("org.freedesktop.portal.FileChooser.OpenFile", 0, config.parentWindow, "Choose File", options).Store(&requestHandle)
- if err != nil {
- return fmt.Errorf("failed to call OpenFile: %w", err)
- }
-
- // Make sure we got the request object's path right. Update our subscription otherwise.
- if requestHandle != config.expectedRequestHandle {
- if err := conn.AddMatchSignal(dbus.WithMatchObjectPath(dbus.ObjectPath(requestHandle))); err != nil {
- return fmt.Errorf("failed to subscribe to request: %w", err)
- }
- // Reset signal handling.
- signals := make(chan *dbus.Signal, 1)
- conn.Signal(signals)
- config.signals = signals
- }
-
- // Wait for the response from the file dialog.
- response := <-config.signals
- uris := extractURIsFromSignal(response)
-
- // Error if no files were selected.
- if len(uris) < 1 {
- return ErrUserDecline
- }
-
- // Remove the protocol from the URI.
- parsedURL, err := url.Parse(uris[0])
- if err != nil {
- return fmt.Errorf("failed parsing file path %s: %w", uris[0], err)
- }
- filepath = parsedURL.Path
- return nil
- }); err != nil {
+ vs, err := e.open(configOpen{
+ label: "Choose File",
+ extensions: extensions,
+ })
+ if err != nil {
return nil, err
}
- return os.Open(filepath)
+ return vs[0], nil
}
// importFiles opens a multi-file picker to choose multiple files.
func (e *Explorer) importFiles(extensions ...string) ([]io.ReadCloser, error) {
+ vs, err := e.open(configOpen{
+ label: "Choose Files",
+ extensions: extensions,
+ multi: true,
+ })
+ if err != nil {
+ return nil, err
+ }
+ return vs, nil
+}
+
+func (e *Explorer) open(cfg configOpen) ([]io.ReadCloser, error) {
var filepaths []string
if err := e.withDesktopPortal(func(conn *dbus.Conn, desktopPortal dbus.BusObject, config config) error {
// Invoke the OpenFile method.
requestHandle := ""
options := map[string]dbus.Variant{
"handle_token": dbus.MakeVariant(config.handleToken),
- "multiple": dbus.MakeVariant(true),
+ "multiple": dbus.MakeVariant(cfg.multi),
+ "directory": dbus.MakeVariant(cfg.dir),
}
- if len(extensions) > 0 {
- options["filters"] = makeFilter(extensions)
+ if len(cfg.extensions) > 0 {
+ options["filters"] = makeFilter(cfg.extensions)
}
- err := desktopPortal.Call("org.freedesktop.portal.FileChooser.OpenFile", 0, config.parentWindow, "Choose File", options).Store(&requestHandle)
+ err := desktopPortal.Call("org.freedesktop.portal.FileChooser.OpenFile", 0, config.parentWindow, cfg.label, options).Store(&requestHandle)
if err != nil {
return fmt.Errorf("failed to call OpenFile: %w", err)
}
@@ 328,6 310,7 @@ func (e *Explorer) importFiles(extensions ...string) ([]io.ReadCloser, error) {
}); err != nil {
return nil, err
}
+
rcs := make([]io.ReadCloser, 0, len(filepaths))
for _, fname := range filepaths {
rc, err := os.Open(fname)
@@ 339,5 322,6 @@ func (e *Explorer) importFiles(extensions ...string) ([]io.ReadCloser, error) {
}
rcs = append(rcs, rc)
}
+
return rcs, nil
}