Notifications
Real-time push notifications for calls, messages, and voicemails across all platforms.
Setup
Request Permissions
const granted = await dial.notifications.requestPermissions();
if (granted) {
console.log('Notifications enabled');
} else {
console.log('Notifications denied');
}Register for Push Notifications
await dial.notifications.register();Notification Types
Call Notifications
// Incoming call
dial.on('notification:call:incoming', (notification) => {
console.log('Incoming call from:', notification.from);
console.log('Call type:', notification.callType); // 'audio' | 'video'
});
// Missed call
dial.on('notification:call:missed', (notification) => {
console.log('Missed call from:', notification.from);
});Message Notifications
dial.on('notification:message', (notification) => {
console.log('New message from:', notification.from);
console.log('Message preview:', notification.preview);
});Voicemail Notifications
dial.on('notification:voicemail', (notification) => {
console.log('New voicemail from:', notification.from);
console.log('Duration:', notification.duration);
console.log('Transcription:', notification.transcription);
});Notification Object
interface Notification {
id: string;
type: 'call' | 'message' | 'voicemail';
from: string; // Wallet address
timestamp: Date;
title: string;
body: string;
data: any; // Type-specific data
priority: 'high' | 'normal' | 'low';
}Handling Notifications
Click/Tap Actions
dial.notifications.onClicked((notification) => {
switch (notification.type) {
case 'call':
// Navigate to call screen
navigateToCall(notification.data.callId);
break;
case 'message':
// Navigate to chat
navigateToChat(notification.from);
break;
case 'voicemail':
// Navigate to voicemail
navigateToVoicemail(notification.data.voicemailId);
break;
}
});Actions
// Add quick action buttons to notifications
await dial.notifications.setActions({
call: [
{ action: 'answer', title: 'Answer' },
{ action: 'decline', title: 'Decline' }
],
message: [
{ action: 'reply', title: 'Reply' },
{ action: 'mark_read', title: 'Mark as Read' }
]
});
// Handle actions
dial.notifications.onAction((action, notification) => {
switch (action) {
case 'answer':
dial.calls.answer(notification.data.callId);
break;
case 'decline':
dial.calls.decline(notification.data.callId);
break;
case 'reply':
openQuickReply(notification.from);
break;
}
});Notification Preferences
Enable/Disable by Type
await dial.notifications.setPreferences({
calls: true,
messages: true,
voicemails: true,
conferenceInvites: false
});Quiet Hours
await dial.notifications.setQuietHours({
enabled: true,
start: '22:00', // 10 PM
end: '08:00', // 8 AM
timezone: 'America/New_York'
});Priority Contacts
// Always notify for these contacts, even during quiet hours
await dial.notifications.setPriorityContacts([
'0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
'0x8ba1f109551bD432803012645Ac136ddd64DBA72'
]);Sound & Vibration
await dial.notifications.setSound({
enabled: true,
sound: 'default', // or custom sound URL
vibrate: true,
vibrationPattern: [0, 200, 100, 200] // ms
});Badge Count
// Get unread count
const count = await dial.notifications.getBadgeCount();
console.log(`${count} unread notifications`);
// Clear badge
await dial.notifications.clearBadge();Notification History
// Get notification history
const history = await dial.notifications.getHistory({
limit: 50,
unreadOnly: false
});
// Mark as read
await dial.notifications.markAsRead(notificationId);
// Delete notification
await dial.notifications.delete(notificationId);
// Clear all notifications
await dial.notifications.clearAll();Platform-Specific Features
Web Push Notifications
// Request web push notification permission
if ('Notification' in window && 'serviceWorker' in navigator) {
const permission = await Notification.requestPermission();
if (permission === 'granted') {
await dial.notifications.register();
}
}iOS (APNs)
// Handled automatically by iOS SDK
// Configure in your app delegate:
import DialSDK
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
DialClient.shared.registerForPushNotifications(deviceToken: deviceToken)
}Android (FCM)
// Configure Firebase Cloud Messaging
import wtf.dial.sdk.DialClient
class MyFirebaseMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
DialClient.getInstance().registerPushToken(token)
}
}Rich Notifications
With Images
await dial.notifications.send({
to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
title: 'Shared a photo',
body: 'Check out this image!',
image: 'https://example.com/image.jpg'
});With Inline Reply
// Enable inline reply for messages
dial.notifications.onInlineReply((reply, notification) => {
dial.messages.send({
to: notification.from,
content: reply,
type: 'text'
});
});Complete Example: Notification Manager
import { useState, useEffect } from 'react';
import { DialClient, Notification } from '@dial/sdk';
export function NotificationManager({ dial }) {
const [notifications, setNotifications] = useState<Notification[]>([]);
const [badgeCount, setBadgeCount] = useState(0);
const [preferences, setPreferences] = useState({
calls: true,
messages: true,
voicemails: true
});
useEffect(() => {
setupNotifications();
loadNotificationHistory();
}, []);
const setupNotifications = async () => {
// Request permission
const granted = await dial.notifications.requestPermissions();
if (granted) {
await dial.notifications.register();
}
// Listen for new notifications
dial.on('notification:received', (notification) => {
setNotifications(prev => [notification, ...prev]);
setBadgeCount(prev => prev + 1);
// Show browser notification
if ('Notification' in window && Notification.permission === 'granted') {
new Notification(notification.title, {
body: notification.body,
icon: '/icon.png'
});
}
});
// Handle notification clicks
dial.notifications.onClicked((notification) => {
handleNotificationClick(notification);
markAsRead(notification.id);
});
};
const loadNotificationHistory = async () => {
const history = await dial.notifications.getHistory({
limit: 50
});
setNotifications(history);
const count = await dial.notifications.getBadgeCount();
setBadgeCount(count);
};
const handleNotificationClick = (notification: Notification) => {
switch (notification.type) {
case 'call':
// Navigate to call
break;
case 'message':
// Navigate to chat
break;
case 'voicemail':
// Navigate to voicemail
break;
}
};
const markAsRead = async (notificationId: string) => {
await dial.notifications.markAsRead(notificationId);
setNotifications(prev =>
prev.map(n =>
n.id === notificationId ? { ...n, read: true } : n
)
);
setBadgeCount(prev => Math.max(0, prev - 1));
};
const updatePreferences = async (newPrefs: any) => {
await dial.notifications.setPreferences(newPrefs);
setPreferences(newPrefs);
};
return (
<div className="notification-manager">
<div className="header">
<h2>Notifications</h2>
{badgeCount > 0 && (
<span className="badge">{badgeCount}</span>
)}
</div>
<div className="preferences">
<label>
<input
type="checkbox"
checked={preferences.calls}
onChange={(e) =>
updatePreferences({ ...preferences, calls: e.target.checked })
}
/>
Call notifications
</label>
<label>
<input
type="checkbox"
checked={preferences.messages}
onChange={(e) =>
updatePreferences({ ...preferences, messages: e.target.checked })
}
/>
Message notifications
</label>
<label>
<input
type="checkbox"
checked={preferences.voicemails}
onChange={(e) =>
updatePreferences({ ...preferences, voicemails: e.target.checked })
}
/>
Voicemail notifications
</label>
</div>
<div className="notification-list">
{notifications.map(notification => (
<div
key={notification.id}
className={`notification ${notification.read ? 'read' : 'unread'}`}
onClick={() => handleNotificationClick(notification)}
>
<div className="icon">
{notification.type === 'call' && '📞'}
{notification.type === 'message' && '💬'}
{notification.type === 'voicemail' && '🎙️'}
</div>
<div className="content">
<div className="title">{notification.title}</div>
<div className="body">{notification.body}</div>
<div className="time">
{notification.timestamp.toLocaleString()}
</div>
</div>
{!notification.read && <div className="unread-dot" />}
</div>
))}
</div>
</div>
);
}Testing Notifications
// Send test notification
await dial.notifications.sendTest({
type: 'call',
title: 'Test Call',
body: 'This is a test notification'
});Next Steps
Last updated on