1import AppKit23@MainActor4protocol WallpaperManaging {5 func download(from url: URL) async throws -> URL6 func setDesktopImage(from fileURL: URL, screen: NSScreen?) throws7 func saveToFolder(from sourceURL: URL, to folderURL: URL) throws8}910@MainActor11protocol DesktopImageSetting {12 func setDesktopImageURL(13 _ url: URL, for screen: NSScreen, options: [NSWorkspace.DesktopImageOptionKey: Any]14 ) throws15}1617extension NSWorkspace: DesktopImageSetting {}1819class WallpaperManager: WallpaperManaging {20 static let shared = WallpaperManager()2122 private let session: URLSession23 private let desktopSetter: @MainActor (URL, NSScreen) throws -> Void2425 init(26 session: URLSession = .shared,27 desktopSetter: (@MainActor (URL, NSScreen) throws -> Void)? = nil,28 workspace: DesktopImageSetting = NSWorkspace.shared29 ) {30 self.session = session31 self.desktopSetter =32 desktopSetter ?? { url, screen in33 try workspace.setDesktopImageURL(34 url, for: screen, options: [:]35 )36 }37 }3839 40 func download(from url: URL) async throws -> URL {41 let (data, response) = try await session.data(from: url)42 guard let response = response as? HTTPURLResponse,43 (200...299).contains(response.statusCode)44 else {45 throw WallhavenError.apiError("Wallpaper download failed")46 }4748 let filename = url.lastPathComponent49 let tempDir = FileManager.default.temporaryDirectory50 let fileURL = tempDir.appendingPathComponent(filename)5152 try data.write(to: fileURL)53 return fileURL54 }5556 57 @MainActor58 func setDesktopImage(from fileURL: URL, screen: NSScreen? = nil) throws {59 if let screen = screen {60 try desktopSetter(fileURL, screen)61 } else {62 63 64 65 let targetScreen = NSScreen.main ?? NSScreen.screens.first!66 try desktopSetter(fileURL, targetScreen)67 }68 }6970 71 func saveToFolder(from sourceURL: URL, to folderURL: URL) throws {72 73 try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true)7475 let destinationURL = folderURL.appendingPathComponent(sourceURL.lastPathComponent)7677 78 79 if FileManager.default.fileExists(atPath: destinationURL.path) {80 try FileManager.default.removeItem(at: destinationURL)81 }8283 try FileManager.default.copyItem(at: sourceURL, to: destinationURL)84 }8586 87 @MainActor88 func setWallpaper(from url: URL, screen: NSScreen? = nil) async throws {89 let localURL = try await download(from: url)90 try setDesktopImage(from: localURL, screen: screen)91 }92}