ce55be4a-fb5f-4981-b507-0f4.../Sources/services/AirDropService.swift

56 lines
1.8 KiB
Swift
Raw Permalink Normal View History

//
// AirDropService.swift
// MioIsland AirDrop Plugin
//
// Thin wrapper around NSSharingService(.sendViaAirDrop). This is a
// 100% public Apple API no entitlements, no permissions, no
// private frameworks. When invoked, macOS pops the native AirDrop
// chooser sheet; we don't render the device list ourselves.
//
import AppKit
import Foundation
enum AirDropError: Error, LocalizedError {
case serviceUnavailable
case cannotPerform
var errorDescription: String? {
switch self {
case .serviceUnavailable:
return L10n.errServiceUnavailable
case .cannotPerform:
return L10n.errCannotPerform
}
}
}
enum AirDropService {
/// Invoke macOS' AirDrop chooser for the given files.
///
/// NSSharingService does NOT surface per-recipient completion,
/// so we can only distinguish "could not start" vs "started and
/// returned control to us". A returned .success(()) means the
/// chooser sheet was presented; the user may have cancelled it,
/// but from our UI perspective we treat it as handled.
static func perform(
files: [URL],
completion: @escaping (Result<Void, Error>) -> Void
) {
DispatchQueue.main.async {
guard let service = NSSharingService(named: .sendViaAirDrop) else {
completion(.failure(AirDropError.serviceUnavailable))
return
}
guard service.canPerform(withItems: files) else {
completion(.failure(AirDropError.cannotPerform))
return
}
service.perform(withItems: files)
// AirDrop chooser is modal; perform() returns right after
// presenting. Treat that as success.
completion(.success(()))
}
}
}