~whereswaldon/gio-x

a8f5094dcb965cd6bbfe39beead2c2bcd4d6e192 — Sebastien Binet 4 months ago e4e582a
explorer: refactor importFile{,s} for Linux

This CL refactors `importFile{,s}` for Linux.
it also prepares for the ability to modify the "label" of the file(s)
opening dialog.
(so this can be adapted for localization/internationalization.)

Signed-off-by: Sebastien Binet <binet@cern.ch>
1 files changed, 32 insertions(+), 48 deletions(-)

M explorer/explorer_linux.go
M explorer/explorer_linux.go => explorer/explorer_linux.go +32 -48
@@ 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
}