WallpaperManager.swift

2.9 KB · raw

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}910class WallpaperManager: WallpaperManaging {11  static let shared = WallpaperManager()1213  private let session: URLSession14  private let desktopSetter: @MainActor (URL, NSScreen) throws -> Void1516  init(17    session: URLSession = .shared,18    desktopSetter: @escaping @MainActor (URL, NSScreen) throws -> Void =19      WallpaperManager.applyDesktopImage20  ) {21    self.session = session22    self.desktopSetter = desktopSetter23  }2425  private static func applyDesktopImage(_ url: URL, _ screen: NSScreen) throws {26    try NSWorkspace.shared.setDesktopImageURL(url, for: screen, options: [:])27  }2829  /// Downloads the file to a temporary location and returns the local URL.30  func download(from url: URL) async throws -> URL {31    let (data, response) = try await session.data(from: url)32    guard let response = response as? HTTPURLResponse,33      (200...299).contains(response.statusCode)34    else {35      throw WallhavenError.apiError("Wallpaper download failed")36    }3738    let filename = url.lastPathComponent39    let tempDir = FileManager.default.temporaryDirectory40    let fileURL = tempDir.appendingPathComponent(filename)4142    try data.write(to: fileURL)43    return fileURL44  }4546  /// Sets the desktop image from a local file URL.47  @MainActor48  func setDesktopImage(from fileURL: URL, screen: NSScreen? = nil) throws {49    if let screen = screen {50      try desktopSetter(fileURL, screen)51    } else {52      // Set for all screens or just main? Let's default to main for safety,53      // but the UI will likely drive this.54      // If no screen specified, maybe set for the 'active' one.55      let targetScreen = NSScreen.main ?? NSScreen.screens.first!56      try desktopSetter(fileURL, targetScreen)57    }58  }5960  /// Copies the file to the specified destination directory.61  func saveToFolder(from sourceURL: URL, to folderURL: URL) throws {62    // Ensure folder exists63    try FileManager.default.createDirectory(at: folderURL, withIntermediateDirectories: true)6465    let destinationURL = folderURL.appendingPathComponent(sourceURL.lastPathComponent)6667    // If file exists, maybe don't overwrite or handle gracefully?68    // For now, we'll remove it if it exists to ensure we have the fresh one, or just skip.69    if FileManager.default.fileExists(atPath: destinationURL.path) {70      try FileManager.default.removeItem(at: destinationURL)71    }7273    try FileManager.default.copyItem(at: sourceURL, to: destinationURL)74  }7576  // Legacy support wrapper (optional, but cleaner to update call sites)77  @MainActor78  func setWallpaper(from url: URL, screen: NSScreen? = nil) async throws {79    let localURL = try await download(from: url)80    try setDesktopImage(from: localURL, screen: screen)81  }82}