Notifications¶
Nib provides full access to macOS system notifications, including instant push, scheduled delivery, custom sounds, action buttons, and text input.
Built app only
macOS delivers notifications to app bundles. Under nib run, app.notify() and push() fall back to a basic AppleScript banner without actions or sounds, and scheduling is unavailable. Test notifications with nib build.
Quick Notification¶
The simplest way to send a notification is app.notify():
import nib
def main(app: nib.App):
app.title = "Notify"
app.icon = nib.SFSymbol("bell")
app.width = 200
app.height = 100
app.build(
nib.Button("Send Notification", action=lambda: app.notify("Hello!", "World"))
)
nib.run(main)
app.notify() parameters¶
app.notify(
"Download Complete",
body="report.pdf has been saved to Downloads",
subtitle="File Manager",
sound=True,
)
Requesting Permission¶
macOS requires user permission before delivering notifications. Request it early:
def on_permission(granted):
if granted:
print("Notifications enabled")
else:
print("Notifications denied")
app.notifications.request_permission(callback=on_permission)
Note
The first call shows the system permission dialog. Subsequent calls return the cached result. If the user denied permission, they must re-enable it in System Settings.
Notification Objects¶
For full control, create Notification objects and push them through the notification manager:
from nib import Notification
notification = Notification(
title="New Message",
body="You have a new message from Alice",
subtitle="Messages",
)
app.notifications.push(notification)
Custom sounds¶
Use NotificationSound to configure the notification sound:
from nib import Notification, NotificationSound, NotificationSoundName
# Default sound
notification = Notification(
title="Alert",
body="Something happened",
sound=NotificationSound(name=NotificationSoundName.DEFAULT),
)
# Built-in macOS sound by name
notification = Notification(
title="Alert",
body="Something happened",
sound=NotificationSound(name=NotificationSoundName.custom("Glass")),
)
# Other built-in sounds: "Frog", "Ping", "Pop", "Purr", "Sosumi", "Tink"
Scheduling Notifications¶
Schedule at a specific time¶
from datetime import datetime, timedelta
from nib import Notification
reminder = Notification(
title="Break Time",
body="You have been working for 2 hours. Take a break!",
)
# Schedule for 1 hour from now
notification_id = app.notifications.schedule(
reminder,
at=datetime.now() + timedelta(hours=1),
)
Schedule daily recurring¶
from nib import Notification
daily_reminder = Notification(
title="Daily Standup",
body="Time for the morning standup meeting",
)
# Every day at 9:00 AM
app.notifications.schedule_daily(
daily_reminder,
from_time="09:00",
)
# Multiple times per day between 8 AM and 6 PM
app.notifications.schedule_daily(
daily_reminder,
from_time="08:00",
to_time="18:00",
count=3,
)
# Daily for one week
from datetime import date, timedelta
app.notifications.schedule_daily(
daily_reminder,
from_time="09:00",
from_date=date.today(),
to_date=date.today() + timedelta(days=7),
)
Reschedule¶
Cancel and reschedule an existing notification:
app.notifications.reschedule(
reminder,
at=datetime.now() + timedelta(hours=2),
)
Notification Actions¶
Actions appear as buttons on the notification. Users can tap them to trigger callbacks without opening the app.
from nib import Notification, NotificationAction, TextInputNotificationAction
notification = Notification(
title="New Message",
body="Alice: Hey, are you free for lunch?",
actions=[
NotificationAction(
id="reply",
title="Reply",
text_input=TextInputNotificationAction(
button_title="Send",
placeholder="Type your reply...",
),
),
NotificationAction(
id="mark_read",
title="Mark as Read",
),
],
)
app.notifications.push(notification)
Handling action callbacks¶
Register a handler to receive action events:
def handle_action(notification_id, action_id, user_text):
if action_id == "reply" and user_text:
print(f"User replied: {user_text}")
elif action_id == "mark_read":
print("Marked as read")
unsubscribe = app.notifications.on_action(handle_action)
# unsubscribe()
The callback receives three arguments:
Action options¶
from nib import NotificationAction, NotificationActionOption
NotificationAction(
id="delete",
title="Delete",
options=[
NotificationActionOption.DESTRUCTIVE, # Red button
NotificationActionOption.AUTHENTICATION_REQUIRED, # Requires unlock
],
)
NotificationAction(
id="open",
title="Open App",
options=[NotificationActionOption.FOREGROUND], # Brings app to front
)
Canceling Notifications¶
# Cancel a specific notification by ID
app.notifications.cancel_notification(notification_id)
# Cancel all scheduled and delivered notifications
app.notifications.cancel_all_notifications()
Querying Notifications¶
Retrieve notifications that are currently scheduled or displayed in Notification Center:
# Get all scheduled (pending) notifications
def on_scheduled(notifications):
for n in notifications:
print(f"Scheduled: {n.title} (id: {n.id})")
app.notifications.get_all_scheduled_notifications(on_scheduled)
# Get all delivered (visible in Notification Center) notifications
def on_delivered(notifications):
print(f"{len(notifications)} notifications showing")
app.notifications.get_all_delivered_notifications(on_delivered)
# Get a specific notification by ID
app.notifications.get_scheduled_notification(
"some-id",
callback=lambda n: print(f"Found: {n.title}") if n else print("Not found"),
)
Related¶
- Notification, NotificationManager, Sounds and actions
- Permissions:
app.permissions.check() - App:
app.notify()