native-dialog 0.9.6

A library to display dialogs. Supports GNU/Linux, BSD Unix, macOS and Windows.
Documentation
use std::cell::Cell;

use block2::RcBlock;
use objc2::Message;
use objc2_app_kit::{NSAlert, NSModalResponse, NSWindow};

use super::DispatchResponse;
use crate::ffi::UnsafeWindowHandle;

pub trait NSAlertAsyncExt {
    fn spawn(&self, owner: UnsafeWindowHandle) -> DispatchResponse<NSModalResponse>;

    fn begin<T, F>(&self, owner: Option<&NSWindow>, callback: F) -> DispatchResponse<T>
    where
        T: Default + Send + 'static,
        F: Fn(&NSAlert, NSModalResponse) -> T + Send + 'static;
}

impl NSAlertAsyncExt for NSAlert {
    fn spawn(&self, owner: UnsafeWindowHandle) -> DispatchResponse<NSModalResponse> {
        let owner = unsafe { owner.as_appkit() };
        self.begin(owner.as_deref(), move |_, response| response)
    }

    fn begin<T, F>(&self, owner: Option<&NSWindow>, callback: F) -> DispatchResponse<T>
    where
        T: Default + Send + 'static,
        F: Fn(&NSAlert, NSModalResponse) -> T + Send + 'static,
    {
        let (send, recv) = futures_channel::oneshot::channel();

        let cell = Cell::new(Some(send));
        let alert = self.retain();
        let handler = move |response: NSModalResponse| {
            if let Some(send) = cell.take() {
                let _ = send.send(callback(&alert, response));
            }
        };

        match owner {
            Some(window) => {
                let block = RcBlock::new(handler);
                self.beginSheetModalForWindow_completionHandler(window, Some(&block))
            }
            None => handler(self.runModal()),
        }

        DispatchResponse::new(recv)
    }
}