From bbeb89b9bad7ba24a40a017eddb00f69645b231f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Orzech?= Date: Wed, 4 Feb 2026 14:06:53 +0100 Subject: [PATCH] Show installed browser options --- .../MacTorn/Utilities/BrowserManager.swift | 66 ++++++++++++++++--- MacTorn/MacTorn/Views/SettingsView.swift | 12 +++- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/MacTorn/MacTorn/Utilities/BrowserManager.swift b/MacTorn/MacTorn/Utilities/BrowserManager.swift index 30c5105..087eeba 100644 --- a/MacTorn/MacTorn/Utilities/BrowserManager.swift +++ b/MacTorn/MacTorn/Utilities/BrowserManager.swift @@ -7,26 +7,77 @@ enum PreferredBrowser: String, CaseIterable, Identifiable { case firefox = "Firefox" case edge = "Microsoft Edge" case brave = "Brave" + case arc = "Arc" + case vivaldi = "Vivaldi" + case zen = "Zen" + case opera = "Opera" + case duckduckgo = "DuckDuckGo" + case orion = "Orion" + case tor = "Tor Browser" + case chromium = "Chromium" + case librewolf = "LibreWolf" + case waterfox = "Waterfox" + case atlas = "ChatGPT Atlas" var id: String { rawValue } - var bundleIdentifier: String? { + var bundleIdentifiers: [String]? { switch self { case .system: return nil case .safari: - return "com.apple.Safari" + return ["com.apple.Safari"] case .chrome: - return "com.google.Chrome" + return ["com.google.Chrome"] case .firefox: - return "org.mozilla.firefox" + return ["org.mozilla.firefox"] case .edge: - return "com.microsoft.edgemac" + return ["com.microsoft.edgemac"] case .brave: - return "com.brave.Browser" + return ["com.brave.Browser"] + case .arc: + return ["company.thebrowser.Browser"] + case .vivaldi: + return ["com.vivaldi.Vivaldi"] + case .zen: + return ["app.zen-browser.zen"] + case .opera: + return ["com.operasoftware.Opera"] + case .duckduckgo: + return ["com.duckduckgo.macos.browser"] + case .orion: + return ["com.kagi.kagimacOS", "com.kagi.kagimacOS.RC"] + case .tor: + return ["com.torproject.tor"] + case .chromium: + return ["org.chromium.Chromium"] + case .librewolf: + return ["io.gitlab.librewolf-community"] + case .waterfox: + return ["net.waterfox.waterfox"] + case .atlas: + return ["com.openai.atlas"] } } + var installedApplicationURL: URL? { + guard let bundleIdentifiers else { return nil } + for bundleIdentifier in bundleIdentifiers { + if let appURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) { + return appURL + } + } + return nil + } + + var isInstalled: Bool { + self == .system || installedApplicationURL != nil + } + + static func availableBrowsers() -> [PreferredBrowser] { + PreferredBrowser.allCases.filter { $0.isInstalled } + } + init(storedValue: String?) { guard let storedValue, let value = PreferredBrowser(rawValue: storedValue) else { @@ -50,8 +101,7 @@ final class BrowserManager { } let preference = PreferredBrowser(storedValue: UserDefaults.standard.string(forKey: "preferredBrowser")) - guard let bundleIdentifier = preference.bundleIdentifier, - let appURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleIdentifier) else { + guard let appURL = preference.installedApplicationURL else { NSWorkspace.shared.open(url) return } diff --git a/MacTorn/MacTorn/Views/SettingsView.swift b/MacTorn/MacTorn/Views/SettingsView.swift index 32d87b3..055d3d7 100644 --- a/MacTorn/MacTorn/Views/SettingsView.swift +++ b/MacTorn/MacTorn/Views/SettingsView.swift @@ -7,6 +7,7 @@ struct SettingsView: View { @AppStorage("preferredBrowser") private var preferredBrowser: String = PreferredBrowser.system.rawValue @State private var inputKey: String = "" @State private var showCredits: Bool = false + @State private var availableBrowsers: [PreferredBrowser] = PreferredBrowser.availableBrowsers() // Developer ID for tip feature (bombel) private let developerID = 2362436 @@ -114,7 +115,7 @@ struct SettingsView: View { .frame(width: 20) Picker("Preferred Browser", selection: $preferredBrowser) { - ForEach(PreferredBrowser.allCases) { browser in + ForEach(availableBrowsers) { browser in Text(browser.rawValue).tag(browser.rawValue) } } @@ -230,6 +231,15 @@ struct SettingsView: View { .frame(width: 320) .onAppear { inputKey = appState.apiKey + refreshAvailableBrowsers() + } + } + + private func refreshAvailableBrowsers() { + let browsers = PreferredBrowser.availableBrowsers() + availableBrowsers = browsers + if !browsers.contains(where: { $0.rawValue == preferredBrowser }) { + preferredBrowser = PreferredBrowser.system.rawValue } }