From 51b2fe914828a5bb26007f963647cc8a079e6027 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 12 Apr 2026 00:22:38 +0000 Subject: [PATCH] Skip Spotify AppleScript when Spotify isn't installed (fix #8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On every launch, NowPlayingManager runs fetchSpotifyViaAppleScript as part of its source-detection polling. That script contains a `tell application "Spotify"` block, and even though the script guards with `if not (exists process "Spotify") then return "NOT_RUNNING"` inside a System Events tell, AppleScript still resolves the second `tell application "Spotify"` by bundle identifier at compile time. When Spotify.app isn't installed, macOS can't find the bundle and pops up a "Where is Spotify?" Finder picker. Gate fetchSpotifyViaAppleScript and fetchSpotifyArtwork on a new isSpotifyInstalled() helper that checks NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.spotify.client"). When Spotify isn't installed we never hand the AppleScript to macOS, so no Finder picker appears. The playback-control AppleScripts (play/pause/next/prev/seek) don't need the same guard — they are only reached once sourceName has already been set to "Spotify", which requires Spotify to be running, and they additionally bail via isApplicationRunning("Spotify") in togglePlayPause. --- .../Modules/NowPlaying/NowPlayingManager.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/SuperIsland/Modules/NowPlaying/NowPlayingManager.swift b/SuperIsland/Modules/NowPlaying/NowPlayingManager.swift index 5fbdced..29c8d71 100644 --- a/SuperIsland/Modules/NowPlaying/NowPlayingManager.swift +++ b/SuperIsland/Modules/NowPlaying/NowPlayingManager.swift @@ -507,6 +507,11 @@ final class NowPlayingManager: ObservableObject { } nonisolated private func fetchSpotifyViaAppleScript() -> Bool { + // Don't compile any `tell application "Spotify"` AppleScript when + // Spotify isn't installed — doing so causes macOS to pop the + // "Where is Spotify?" Finder picker on every launch (issue #8). + guard isSpotifyInstalled() else { return false } + let script = """ tell application "System Events" if not (exists process "Spotify") then return "NOT_RUNNING" @@ -552,6 +557,8 @@ final class NowPlayingManager: ObservableObject { } nonisolated private func fetchSpotifyArtwork() { + guard isSpotifyInstalled() else { return } + let script = """ tell application "Spotify" return artwork url of current track @@ -1091,6 +1098,10 @@ final class NowPlayingManager: ObservableObject { .replacingOccurrences(of: "\"", with: "\\\"") } + nonisolated private func isSpotifyInstalled() -> Bool { + NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.spotify.client") != nil + } + private func isApplicationRunning(_ name: String) -> Bool { NSWorkspace.shared.runningApplications.contains { app in app.localizedName == name && !app.isTerminated