From ec4a3d024915114bd770bd98ea6eba7958e1a9ca Mon Sep 17 00:00:00 2001 From: Gavin Nugent Date: Thu, 7 May 2026 10:19:31 +0100 Subject: [PATCH] Add Transcode entry to Nautilus context menu (#5635) * Add Transcode entry to Nautilus context menu Right-click on image or video files in Nautilus to send them to omarchy-transcode in a presentation terminal, mirroring the existing LocalSend integration. Co-Authored-By: Claude Opus 4.7 (1M context) * Use shlex.quote for shell-safe command construction in transcode.py Quote both the resolved binary path and file paths via shlex.quote instead of a custom escaper. Addresses Copilot review on #5635. Co-Authored-By: Claude Opus 4.7 (1M context) * Style changes --------- Co-authored-by: Claude Opus 4.7 (1M context) Co-authored-by: David Heinemeier Hansson --- .../nautilus-python/extensions/transcode.py | 94 +++++++++++++++++++ install/config/nautilus-python.sh | 1 + migrations/1778099894.sh | 3 + 3 files changed, 98 insertions(+) create mode 100644 default/nautilus-python/extensions/transcode.py create mode 100644 migrations/1778099894.sh diff --git a/default/nautilus-python/extensions/transcode.py b/default/nautilus-python/extensions/transcode.py new file mode 100644 index 00000000..be1dfe4b --- /dev/null +++ b/default/nautilus-python/extensions/transcode.py @@ -0,0 +1,94 @@ +import shlex +import shutil + +from gi import require_version + +require_version("Nautilus", "4.1") + +from gi.repository import GObject, Gio, Nautilus + + +SUPPORTED_MIME_PREFIXES = ("image/", "video/") +SUPPORTED_EXTENSIONS = { + ".jpg", ".jpeg", ".png", ".webp", ".gif", ".heic", ".avif", + ".mp4", ".mov", ".m4v", ".mkv", ".webm", ".avi", +} + + +class TranscodeAction(GObject.GObject, Nautilus.MenuProvider): + def _launch_transcode(self, paths): + wrapper = shutil.which("omarchy-launch-floating-terminal-with-presentation") + binary = shutil.which("omarchy-transcode") + if not wrapper or not binary: + return + + if len(paths) == 1: + cmd = shlex.join([binary, paths[0]]) + else: + cmd = "; ".join( + f"echo {shlex.quote(f'Transcoding {path}')} && " + f"{shlex.join([binary, path])} || true" + for path in paths + ) + + Gio.Subprocess.new([wrapper, cmd], Gio.SubprocessFlags.NONE) + + def _is_supported(self, file): + mime = file.get_mime_type() or "" + if mime.startswith(SUPPORTED_MIME_PREFIXES): + return True + + location = file.get_location() + if not location: + return False + path = location.get_path() or "" + lower = path.lower() + return any(lower.endswith(ext) for ext in SUPPORTED_EXTENSIONS) + + def _selected_paths(self, files): + paths = [] + seen = set() + + for file in files: + if file.is_directory(): + continue + if not self._is_supported(file): + continue + location = file.get_location() + if not location: + continue + path = location.get_path() + if path and path not in seen: + seen.add(path) + paths.append(path) + return paths + + def _make_item(self, paths): + label = "Transcode" if len(paths) == 1 else f"Transcode {len(paths)} items" + item = Nautilus.MenuItem( + name="OmarchyTranscodeNautilus::transcode", + label=label, + icon="media-playback-start", + ) + item.connect("activate", self._on_activate, paths) + return item + + def _on_activate(self, _menu, paths): + self._launch_transcode(paths) + + def _tools_available(self): + return bool( + shutil.which("omarchy-launch-floating-terminal-with-presentation") + and shutil.which("omarchy-transcode") + ) + + def get_file_items(self, *args): + files = args[0] if len(args) == 1 else args[1] + if not self._tools_available(): + return [] + + paths = self._selected_paths(files) + if not paths: + return [] + + return [self._make_item(paths)] diff --git a/install/config/nautilus-python.sh b/install/config/nautilus-python.sh index fd2ef0f7..76266353 100644 --- a/install/config/nautilus-python.sh +++ b/install/config/nautilus-python.sh @@ -2,3 +2,4 @@ EXTENSIONS_DIR="$HOME/.local/share/nautilus-python/extensions" mkdir -p "$EXTENSIONS_DIR" cp "$OMARCHY_PATH/default/nautilus-python/extensions/localsend.py" "$EXTENSIONS_DIR/" +cp "$OMARCHY_PATH/default/nautilus-python/extensions/transcode.py" "$EXTENSIONS_DIR/" diff --git a/migrations/1778099894.sh b/migrations/1778099894.sh new file mode 100644 index 00000000..bf83d6d1 --- /dev/null +++ b/migrations/1778099894.sh @@ -0,0 +1,3 @@ +echo "Add Transcode entry to Nautilus context menu" + +source $OMARCHY_PATH/install/config/nautilus-python.sh