///|
priv struct NotificationResultBroker {
mut busy : Bool
gate : @async.CondVar
results : Array[@native.NativeNotificationResult]
result_ready : @async.CondVar
}
///|
let notification_result_broker : NotificationResultBroker = NotificationResultBroker::{
busy: false,
gate: @async.CondVar::Cond(),
results: [],
result_ready: @async.CondVar::Cond(),
}
///|
async fn acquire_notification_result_slot() -> Unit {
while notification_result_broker.busy {
notification_result_broker.gate.wait()
}
notification_result_broker.busy = true
}
///|
fn release_notification_result_slot() -> Unit {
notification_result_broker.busy = false
notification_result_broker.gate.broadcast()
}
///|
fn publish_notification_result(
result : @native.NativeNotificationResult,
) -> Unit {
if notification_result_broker.busy {
notification_result_broker.results.push(result)
notification_result_broker.result_ready.broadcast()
}
}
///|
async fn take_notification_result() -> @native.NativeNotificationResult {
while notification_result_broker.results.length() == 0 {
notification_result_broker.result_ready.wait()
}
let result = notification_result_broker.results[0]
ignore(notification_result_broker.results.remove(0))
result
}
///|
/// Failures while starting or waiting for native notification delivery.
pub(all) suberror NotificationDeliveryError {
Native(@native.NativeError)
WaitInterrupted(detail~ : String)
} derive(Debug, Eq)
///|
pub fn NotificationDeliveryError::message(
self : NotificationDeliveryError,
) -> String {
match self {
Native(error) => error.message()
WaitInterrupted(detail~) =>
"notification delivery wait was interrupted: " + detail
}
}
///|
/// Starts one native notification and waits until macOS reports authorization
/// and delivery completion.
#doc(hidden)
pub async fn notification_show_and_wait(
title : String,
body : String,
payload? : String,
) -> @native.NativeNotificationResult raise NotificationDeliveryError {
acquire_notification_result_slot() catch {
error => raise WaitInterrupted(detail=@debug.render(Repr(error)))
}
defer release_notification_result_slot()
@native.notification_show(title, body, payload?) catch {
error => raise Native(error)
}
@async.protect_from_cancel(take_notification_result, resume_on_cancel=true) catch {
error => raise WaitInterrupted(detail=@debug.render(Repr(error)))
}
}