fix: archive only after AirDrop completes; PDF named by send time; Reveal last PDF
This commit is contained in:
@@ -7,7 +7,14 @@ enum Sharing {
|
||||
/// Throws `ShotdeckError.airDropUnavailable` when the service cannot be created,
|
||||
/// `canPerform` is false, or `view` is not in a visible window (a detached view
|
||||
/// never produces an on-screen sheet).
|
||||
static func airDrop(fileURL: URL, from view: NSView) throws {
|
||||
///
|
||||
/// `onFinished` is invoked on the main actor when the sheet completes: `true` for
|
||||
/// `didShareItems`, `false` for `didFailToShareItems` (including user cancel).
|
||||
static func airDrop(
|
||||
fileURL: URL,
|
||||
from view: NSView,
|
||||
onFinished: @escaping @MainActor @Sendable (Bool) async -> Void
|
||||
) throws {
|
||||
guard let service = NSSharingService(named: .sendViaAirDrop),
|
||||
service.canPerform(withItems: [fileURL]) else {
|
||||
throw ShotdeckError.airDropUnavailable
|
||||
@@ -21,7 +28,12 @@ enum Sharing {
|
||||
window.makeKeyAndOrderFront(nil)
|
||||
|
||||
service.subject = fileURL.lastPathComponent
|
||||
let session = AirDropSession(service: service, window: window, view: view)
|
||||
let session = AirDropSession(
|
||||
service: service,
|
||||
window: window,
|
||||
view: view,
|
||||
onFinished: onFinished
|
||||
)
|
||||
AirDropSession.keepAlive(session)
|
||||
service.delegate = session
|
||||
service.perform(withItems: [fileURL])
|
||||
@@ -29,7 +41,9 @@ enum Sharing {
|
||||
}
|
||||
|
||||
/// Retains the sharing service for the life of the picker and supplies the real
|
||||
/// on-screen window as the sheet parent. `NSSharingService.delegate` is weak.
|
||||
/// on-screen window as the sheet parent. `NSSharingService.delegate` is weak, so
|
||||
/// `live` is the strong reference that keeps this object alive until the sheet
|
||||
/// reports success or failure (including cancel).
|
||||
@MainActor
|
||||
private final class AirDropSession: NSObject, NSSharingServiceDelegate {
|
||||
static var live: [AirDropSession] = []
|
||||
@@ -37,11 +51,19 @@ private final class AirDropSession: NSObject, NSSharingServiceDelegate {
|
||||
let service: NSSharingService
|
||||
let window: NSWindow
|
||||
let view: NSView
|
||||
let onFinished: @MainActor @Sendable (Bool) async -> Void
|
||||
private var reported = false
|
||||
|
||||
init(service: NSSharingService, window: NSWindow, view: NSView) {
|
||||
init(
|
||||
service: NSSharingService,
|
||||
window: NSWindow,
|
||||
view: NSView,
|
||||
onFinished: @escaping @MainActor @Sendable (Bool) async -> Void
|
||||
) {
|
||||
self.service = service
|
||||
self.window = window
|
||||
self.view = view
|
||||
self.onFinished = onFinished
|
||||
}
|
||||
|
||||
static func keepAlive(_ session: AirDropSession) {
|
||||
@@ -52,6 +74,15 @@ private final class AirDropSession: NSObject, NSSharingServiceDelegate {
|
||||
Self.live.removeAll { $0 === self }
|
||||
}
|
||||
|
||||
private func report(_ success: Bool) {
|
||||
guard !reported else { return }
|
||||
reported = true
|
||||
Task { @MainActor in
|
||||
await self.onFinished(success)
|
||||
self.drop()
|
||||
}
|
||||
}
|
||||
|
||||
func sharingService(
|
||||
_ sharingService: NSSharingService,
|
||||
sourceWindowForShareItems items: [Any],
|
||||
@@ -70,7 +101,7 @@ private final class AirDropSession: NSObject, NSSharingServiceDelegate {
|
||||
}
|
||||
|
||||
func sharingService(_ sharingService: NSSharingService, didShareItems items: [Any]) {
|
||||
drop()
|
||||
report(true)
|
||||
}
|
||||
|
||||
func sharingService(
|
||||
@@ -78,6 +109,6 @@ private final class AirDropSession: NSObject, NSSharingServiceDelegate {
|
||||
didFailToShareItems items: [Any],
|
||||
error: any Error
|
||||
) {
|
||||
drop()
|
||||
report(false)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user