From 77bf2ef7047c0334aca9d5f0734745210c3da3d3 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 11 Aug 2026 14:24:17 +0200 Subject: [PATCH] Share files and folders with the desktop file chooser (#6707) Sharing a file or folder over LocalSend opened a terminal to run an fzf pick over a find of the whole home directory, which is slow on a large home, shows no previews, and looks nothing like the rest of the desktop. The portal chooser is already how the other pickers here ask. The chooser has a directory mode, so folder sharing asks for one the same way, and neither entry needs a terminal to host a picker anymore. A chooser that never opens is told apart from nobody picking anything, so a portal failure says so rather than passing for a cancelled share. Co-authored-by: Claude Opus 5 --- bin/omarchy-file-select | 11 ++++++++--- bin/omarchy-menu-share | 19 ++++++++++++++----- default/omarchy/omarchy-menu.jsonc | 4 ++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/bin/omarchy-file-select b/bin/omarchy-file-select index 9610a897..6528111e 100755 --- a/bin/omarchy-file-select +++ b/bin/omarchy-file-select @@ -1,8 +1,8 @@ #!/usr/bin/python3 # omarchy:summary=Pick files with the desktop file chooser -# omarchy:args=[--title ] [--multiple] [--extensions "<ext ext...>"] -# omarchy:examples=omarchy file select --title "Send with Tailscale" --multiple | omarchy file select --title "Pick image" --extensions "png svg" +# omarchy:args=[--title <title>] [--multiple] [--directory] [--extensions "<ext ext...>"] +# omarchy:examples=omarchy file select --title "Send with Tailscale" --multiple | omarchy file select --title "Pick image" --extensions "png svg" | omarchy file select --title "Share folder" --directory # Python rather than bash, alone among the commands here, because the portal # answers a request with a Response signal addressed to the connection that @@ -36,6 +36,7 @@ def main(): parser = argparse.ArgumentParser(add_help=False) parser.add_argument("--title", default="Select file") parser.add_argument("--multiple", action="store_true") + parser.add_argument("--directory", action="store_true") parser.add_argument("--extensions", default="") args, unknown = parser.parse_known_args() @@ -77,7 +78,11 @@ def main(): "multiple": GLib.Variant("b", args.multiple), } - if args.extensions: + if args.directory: + options["directory"] = GLib.Variant("b", True) + + # Filters name file formats, which a directory chooser has no use for. + if args.extensions and not args.directory: # Glob matching in the chooser is case-sensitive, so cover both cases. exts = [ext.lstrip(".").lower() for ext in args.extensions.split()] patterns = [(0, "*." + ext) for ext in exts] + [(0, "*." + ext.upper()) for ext in exts] diff --git a/bin/omarchy-menu-share b/bin/omarchy-menu-share index 24206f4f..57d94bea 100755 --- a/bin/omarchy-menu-share +++ b/bin/omarchy-menu-share @@ -22,13 +22,22 @@ elif (($# > 0)); then FILE_ARRAY=("$@") else if [[ $MODE == "folder" ]]; then - # Pick a single folder from home directory - picked=$(find "$HOME" -type d 2>/dev/null | fzf) + select_args=(--title "Share folder" --directory) else - # Pick one or more files from home directory - picked=$(find "$HOME" -type f 2>/dev/null | fzf --multi) + select_args=(--title "Share files" --multiple) fi - [[ -z $picked ]] && exit 0 + + # Command substitution so the chooser's exit status survives: reading it + # through a process substitution reports success for a chooser that never + # opened, which is indistinguishable here from someone deciding not to share. + picked=$(omarchy-file-select "${select_args[@]}") || status=$? + + if ((${status:-0} > 1)); then + omarchy-notification-send -g "" -u critical "Could not share" "The file chooser did not open" + exit 1 + fi + + [[ -n $picked ]] || exit 0 readarray -t FILE_ARRAY <<<"$picked" fi diff --git a/default/omarchy/omarchy-menu.jsonc b/default/omarchy/omarchy-menu.jsonc index b397820c..ef512668 100644 --- a/default/omarchy/omarchy-menu.jsonc +++ b/default/omarchy/omarchy-menu.jsonc @@ -77,8 +77,8 @@ "trigger.reminder.show": {"icon":"󰢌","label":"Show all","action":"omarchy-reminder show"}, "trigger.reminder.clear": {"icon":"󰢌","label":"Clear all","action":"omarchy-reminder clear"}, "trigger.share.clipboard": {"icon":"","label":"Clipboard","action":"omarchy-menu-share clipboard"}, - "trigger.share.file": {"icon":"","label":"File","action":"xdg-terminal-exec --app-id=org.omarchy.terminal bash -c 'omarchy-menu-share file'"}, - "trigger.share.folder": {"icon":"","label":"Folder","action":"xdg-terminal-exec --app-id=org.omarchy.terminal bash -c 'omarchy-menu-share folder'"}, + "trigger.share.file": {"icon":"","label":"File","action":"omarchy-menu-share file"}, + "trigger.share.folder": {"icon":"","label":"Folder","action":"omarchy-menu-share folder"}, "trigger.share.receive": {"icon":"󰥦","label":"Receive","action":"uwsm-app -- localsend"}, "trigger.toggle.idle-lock": {"icon":"󰅶","label":"Stay Awake","action":"omarchy-toggle-idle"}, "trigger.toggle.notifications": {"icon":"󰂛","label":"Notifications","action":"omarchy-toggle-notification-silencing"},