notification

Cross-platform native desktop notification helpers for MoonBit.

desktop
notification
native
moon add justjavac/notification@0.1.5
Download zip
Author
Version
0.1.5
License
MIT
Last updated
26 days ago
Downloads
3K
README

#justjavac/notification

coverage linux macos windows

Cross-platform desktop notifications for MoonBit native targets.

  • One small API for Windows, macOS, and Linux
  • Public entry points: show, show_notification, show_with_window
  • Optional delivery mode: Auto, App, or Cli
  • Support checks: is_supported() and ensure_supported()

#Example

let result = @notification.show("Build finished", title=Some("CI"))

ignore(result)

#Request Type

///|
test "build a notification value" {
let request = @notification.Notification::new(
"Artifacts uploaded",
title=Some("Release"),
level=@notification.Warning,
)

assert_eq(request.body, "Artifacts uploaded")
}

#Notes

  • body must not be empty
  • missing or empty titles fall back to "Lepus"
  • Windows uses a native shell implementation
  • macOS App Notifications use UserNotifications and require an identified .app
  • macOS CLI Notifications use /usr/bin/osascript
  • automatic macOS delivery selects between those paths without bypassing an authorization denial
  • Linux uses notify-send

#
Notification

pub(all) struct Notification {
title : String?
body : String
level : NotificationLevel
} derive(Eq,
Debug
)

Immutable request object used by show_notification.

Keeping the request as a value makes it easy to validate, reuse, and test. title is optional; when omitted, the package falls back to "Lepus". body must be non-empty.

#
Notification::new

fn Notification::new(body : String, title? : String?, level? : NotificationLevel) -> Notification

Builds a notification value with the same defaults used by the convenience show helper.

This constructor does not perform validation; it simply packages the caller input so it can be passed around, reused, or tested before delivery. Validation happens later in show, show_with_window, and show_notification.

body is stored exactly as provided and is expected to contain the user-facing message text. title may be omitted when the caller wants the runtime delivery path to inject the package default title. level defaults to Info.

title may be omitted or set to Some(""), in which case the runtime delivery path later replaces it with the default application name.

Returns a reusable Notification value that can be passed to show_notification, cached for later delivery, or inspected in tests.

Example

test "Notification::new packages fields without validating" {
let request = Notification::new("Body text", title=Some("Title"))
assert_eq(request.body, "Body text")
assert_true(request.title is Some("Title"))
}

#
NotificationDelivery

pub(all) enum NotificationDelivery {
Auto
App
Cli
} derive(Eq,
Debug
)

Selects how a notification is delivered.

  • Auto lets the platform backend choose the appropriate delivery path.
  • App requests app-oriented delivery. On macOS this uses UserNotifications and requires an identified .app bundle.
  • Cli requests command-line delivery. On macOS this uses osascript.

Windows and Linux currently have one delivery path each, so all three modes use that platform's normal backend.

#
NotificationLevel

pub(all) enum NotificationLevel {
Info
Warning
Error
} derive(Eq,
Debug
)

Severity hint passed to the native notification backend.

The package keeps the set intentionally small so the same API remains easy to use across Windows, macOS, and Linux:

  • Info is the default level for routine updates.
  • Warning requests a more attention-grabbing style when the platform supports it.
  • Error requests the strongest available emphasis.

#
ensure_supported

fn ensure_supported() -> Result[Unit, String]

Converts support probing into a Result.

This is helpful when callers want a human-readable failure reason before attempting show or show_notification.

Returns Ok(()) when is_supported() is true. Otherwise it returns Err(message) where message describes the missing platform capability, such as an unavailable runtime service or required executable.

Example

test "ensure_supported reports a reason when unavailable" {
match ensure_supported() {
Ok(_) => ()
Err(message) => assert_true(!message.is_empty())
}
}

#
is_supported

fn is_supported() -> Bool

Returns whether the current runtime can deliver a desktop notification.

The concrete support check is selected at compile time with #cfg(platform=...) and may still depend on runtime prerequisites such as system executables or platform services being available.

This function is a lightweight probe that does not attempt to show a notification. It returns true only when the active backend believes a delivery attempt can be made right now.

On macOS the probe follows the same automatic selection as show: an identified app checks its UserNotifications authorization state, while an unbundled command-line process checks for /usr/bin/osascript. A user who has denied App Notification authorization makes this function return false; a not-yet-determined authorization still returns true because show may request it.

Example

test "is_supported probes capability without delivering" {
let _ : Bool = is_supported()
}

#
show

fn show(body : String, title? : String?, level? : NotificationLevel, delivery? : NotificationDelivery) -> Result[Unit, String]

Displays a desktop notification built from the provided fields.

This convenience wrapper builds a Notification value and then delegates to show_notification, so it follows the same validation and delivery rules.

body must not be empty. When title is omitted or provided as an empty string, the package falls back to "Lepus". The level value is treated as a cross-platform severity hint and is mapped to the closest urgency or emphasis level supported by the active backend. delivery defaults to Auto and may be set to App or Cli to select a path explicitly.

Returns Ok(()) when the notification is accepted by the native backend. Returns Err(...) with the same failure reasons as show_notification.

Example

// Title defaults to the package name; level defaults to `Info`.
let _ = @notification.show("Download complete")

// Or provide a title and raise the severity.
let _ = @notification.show(
"Disk almost full",
title=Some("Storage"),
level=@notification.NotificationLevel::Warning,
)

#
show_notification

fn show_notification(notification : Notification, delivery? : NotificationDelivery) -> Result[Unit, String]

Displays a desktop notification using the current platform backend.

This is the most direct entry point when the caller already has a complete Notification value. The function performs the full delivery pipeline in order:

  • It verifies that desktop notifications are available in the current runtime environment.
  • It normalizes the request by rejecting an empty body and filling in the default title when one is missing or empty.
  • It dispatches the normalized request to the platform backend:

  • Windows uses a native shell notification implementation.
  • macOS uses UserNotifications for an identified app and /usr/bin/osascript for an unbundled command-line process.
  • Linux uses notify-send.

The shared native dispatcher selects the concrete platform backend during compilation. delivery defaults to Auto; on macOS that mode selects the delivery path at runtime from the host application identity. App forces UserNotifications, while Cli forces /usr/bin/osascript.

Returns Ok(()) when the backend reports a successful delivery attempt. Returns Err(...) when notifications are unsupported on the current runtime, when the request body is empty, or when the native backend reports a failure.

Example

let request = @notification.Notification::new(
"Build finished",
title=Some("CI"),
level=@notification.NotificationLevel::Info,
)
let _ = @notification.show_notification(request)

#
show_with_window

fn show_with_window(window_handle : Int64, body : String, title? : String?, level? : NotificationLevel, delivery? : NotificationDelivery) -> Result[Unit, String]

Displays a desktop notification while keeping compatibility with APIs that already track a native window handle.

The window_handle is currently used only by the Windows-oriented calling convention inherited from the reference implementation; other platforms ignore it.

Apart from accepting the extra handle, this function behaves the same as show: it rejects an empty body, applies the default title when needed, checks runtime support, and forwards the request to the selected backend.

Returns Ok(()) on successful delivery and Err(...) when validation, support checks, or backend execution fails.

Example

// `window_handle` is forwarded to the Windows backend and ignored elsewhere.
let _ = @notification.show_with_window(0L, "Render finished")

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io