using System; using System.Diagnostics; using System.IO; namespace ClaudeDo.Ui.Services; public static class ShellOpen { // "nothing to open" (blank/missing path) is not an error — callers stay silent, matching the // existing Directory.Exists/File.Exists guards this helper replaces. /// Opens an http(s) URL in the default browser. Anything else is refused rather than /// handed to the shell — a URL comes from the worker, and `UseShellExecute` would happily run /// a local executable path. public static (bool Ok, string? Error) Url(string? url) { if (string.IsNullOrWhiteSpace(url)) return (false, null); if (!Uri.TryCreate(url, UriKind.Absolute, out var uri) || (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)) return (false, $"Not a web URL: {url}"); try { Process.Start(new ProcessStartInfo { FileName = uri.AbsoluteUri, UseShellExecute = true }); return (true, null); } catch (Exception ex) { return (false, ex.Message); } } public static (bool Ok, string? Error) Path(string? path) { if (string.IsNullOrWhiteSpace(path)) return (false, null); if (!File.Exists(path) && !Directory.Exists(path)) return (false, null); try { Process.Start(new ProcessStartInfo { FileName = path, UseShellExecute = true }); return (true, null); } catch (Exception ex) { return (false, ex.Message); } } }