Documentation

$notify

Send notifications with actions and navigation.

Setup

Define notification channels in src/notifications/:

// src/notifications/+Alerts@high.wh
@prop val title: String
@prop val message: String

<Notification title={title} body={message} />

File naming: +ChannelName@priority.wh

Send Notification

$notify('/Alerts', "Warning", "Battery low")

Priorities

Set priority in the filename:

  • +Alerts@high.wh - High priority (heads-up)
  • +Messages@default.wh - Default priority
  • +Updates@low.wh - Low priority (no sound)
  • +Background@min.wh - Minimal priority

With Actions

// src/notifications/+Messages@high.wh
@prop val title: String
@prop val body: String
@prop val senderId: String

<Notification
  title={title}
  body={body}
  onClick={() => $navigate("/chat/${senderId}")}
>
  <Button
    text="Reply"
    onClick={() => $navigate("/chat/${senderId}?reply=true")}
  />
  <Button
    text="Mark Read"
    onClick={() => markAsRead(senderId)}
  />
</Notification>

Trigger from code:

$notify(
  '/Messages',
  "New Message",
  "Hey, how are you?",
  senderId = "user123"
)

Navigation on Tap

Use onClick to navigate when notification is tapped:

<Notification
  title={title}
  body={body}
  onClick={() => $navigate("/detail/${itemId}")}
/>

With Image

@prop val title: String
@prop val body: String
@prop val imageUrl: String

<Notification
  title={title}
  body={body}
  image={imageUrl}
/>

Complete Example

// src/notifications/+Download@low.wh
@prop val filename: String
@prop val progress: Int

<Notification
  title="Download"
  body="Downloading {filename}"
  progress={progress}
  ongoing={progress < 100}
/>

// Trigger from code
suspend fun downloadFile(url: String, filename: String) {
  for (progress in 0..100 step 10) {
    $notify('/Download', filename = filename, progress = progress)
    delay(500)
  }
}

Notification with Data

// src/notifications/+ShowReminder@default.wh
@prop val showName: String
@prop val episodeName: String
@prop val showId: String
@prop val posterUrl: String

<Notification
  title={showName}
  body="New episode: {episodeName}"
  image={posterUrl}
  onClick={() => $navigate("/show/${showId}")}
>
  <Button
    text="Watch Now"
    onClick={() => $navigate("/watch/${showId}")}
  />
  <Button
    text="Later"
    onClick={() => addToWatchlist(showId)}
  />
</Notification>

Scheduled Notifications

Combine with workers for scheduled notifications:

$dispatch(
  {
    $notify(
      '/Reminder',
      "Reminder",
      "Don't forget to check the app!"
    )
  },
  delay: { hours: 24 }
)

Channel Organization

src/notifications/
├── +Alerts@high.wh       # Important alerts
├── +Messages@high.wh     # Chat messages
├── +Updates@default.wh   # General updates
├── +Downloads@low.wh     # Download progress
└── +Background@min.wh    # Background sync

Users can control notification channels in system settings. Create separate channels for different types of notifications so users can customize their experience.

Notification Properties

  • title - Notification title
  • body - Notification body text
  • image - Large image URL
  • onClick - Handler when notification is tapped
  • progress - Progress bar (0-100)
  • ongoing - Non-dismissible (for progress)
  • autoCancel - Dismiss on tap (default: true)

See Also