diff --git a/src/gui/components/_legacy.py b/src/gui/components/_legacy.py index ce652e5..1483137 100644 --- a/src/gui/components/_legacy.py +++ b/src/gui/components/_legacy.py @@ -254,25 +254,60 @@ def _downloads_dir() -> "Path": return Path.home() / "Downloads" -def _open_in_file_manager(path: "Path") -> bool: - """Open *path* in the host OS's native file manager. +def _open_in_file_manager(folder: "Path", *, select: "Path | None" = None) -> bool: + """Open the OS file manager at *folder*, optionally highlighting *select*. - Returns ``True`` if the command was dispatched (no guarantee the - file manager actually opened — the user might have removed the - default handler). Returns ``False`` on platforms we don't know - how to launch. + Windows + ``explorer /select,`` is preferred when *select* is given — + Explorer pops to the foreground with the freshly-saved file + already highlighted. Falls back to ``explorer ``, then + ``os.startfile`` if both fail; ``os.startfile`` is known to + silently no-op or open behind the active window in some Windows + configurations, which is why we don't lead with it. + macOS + ``open -R `` reveals the file in Finder. + Linux / *BSD + ``xdg-open`` on the folder. No reliable cross-distro way to + highlight a specific file. + + Returns ``True`` if any of the dispatch attempts succeeded + (no guarantee the window actually surfaced — the caller should + surface a fallback path so the user can paste it manually). """ import os import subprocess + + if sys.platform == "win32": + # explorer.exe with /select wants a literal "/select," followed + # by the path — no space between the comma and the filename, or + # Explorer misinterprets and opens "My Computer" instead. + attempts = [] + if select is not None: + attempts.append(["explorer", f"/select,{select}"]) + attempts.append(["explorer", str(folder)]) + for cmd in attempts: + try: + subprocess.Popen(cmd) + return True + except Exception: + continue + try: + os.startfile(str(folder)) # type: ignore[attr-defined] + return True + except Exception: + return False + if sys.platform == "darwin": + try: + if select is not None: + subprocess.Popen(["open", "-R", str(select)]) + else: + subprocess.Popen(["open", str(folder)]) + return True + except Exception: + return False + # Linux / *BSD / etc. try: - if sys.platform == "win32": - os.startfile(str(path)) # type: ignore[attr-defined] - return True - if sys.platform == "darwin": - subprocess.Popen(["open", str(path)]) - return True - # Linux / *BSD / etc. - subprocess.Popen(["xdg-open", str(path)]) + subprocess.Popen(["xdg-open", str(folder)]) return True except Exception: return False @@ -353,13 +388,24 @@ def local_download_button( saved_path_str = st.session_state.get(saved_key) if saved_path_str: + saved_path = Path(saved_path_str) st.success(f"✓ Saved to `{saved_path_str}`") if st.button( "📂 Open Downloads folder", key=open_key, type="secondary", ): - _open_in_file_manager(Path(saved_path_str).parent) + opened = _open_in_file_manager(saved_path.parent, select=saved_path) + if opened: + # The dispatch returned non-zero; the OS may still have + # opened the window behind the active one. Surface a + # confirmation so the user knows we tried. + st.toast(f"Opening {saved_path.parent}", icon="📂") + else: + st.warning( + f"Could not open the file manager from here. " + f"The file is at:\n\n`{saved_path_str}`" + ) # Back-compat alias: existing call sites use the old name. New code