Skip to main content

@54vie/push - Push Notifications

Module for managing push notifications for 54VIE Super App, supporting FCM/APNs and local notifications.

Installation

pnpm add @54vie/push

Setup

import { PushProvider } from '@54vie/push';

function App() {
return (
<PushProvider
onNotificationReceived={(notification) => {
console.log('Received:', notification);
}}
onNotificationOpened={(notification) => {
// Navigate based on notification data
if (notification.data?.orderId) {
navigation.navigate('OrderDetail', { id: notification.data.orderId });
}
}}
>
<MainApp />
</PushProvider>
);
}

Permission & Token

import { usePush, pushService } from '@54vie/push';

function NotificationSetup() {
const {
token,
isPermissionGranted,
requestPermission,
getToken,
} = usePush();

useEffect(() => {
if (!isPermissionGranted) {
requestPermission();
}
}, []);

// Send token to server
useEffect(() => {
if (token) {
api.post('/devices/register', { token });
}
}, [token]);
}

Topic Subscription

import { pushService } from '@54vie/push';

// Subscribe to topics
await pushService.subscribeToTopic('promotions');
await pushService.subscribeToTopic('news');

// Unsubscribe
await pushService.unsubscribeFromTopic('promotions');

Local Notifications

import { useLocalNotification, localNotificationService } from '@54vie/push';

function OrderConfirmation() {
const { schedule, cancel, cancelAll } = useLocalNotification();

// Schedule notification
const remindPickup = async () => {
const id = await schedule({
title: 'Order Ready',
body: 'Your order is ready for pickup!',
data: { orderId: '123' },
scheduledAt: new Date(Date.now() + 30 * 60 * 1000), // 30 min
});

// Save ID to cancel later if needed
setReminderId(id);
};

// Cancel
const cancelReminder = () => {
cancel(reminderId);
};
}

Recurring Notifications

await schedule({
title: 'Daily Reminder',
body: 'Check your orders!',
repeatType: 'day',
scheduledAt: new Date(), // Start time
});

Action Buttons

// Create category with actions
await localNotificationService.createCategory('order', [
{ id: 'accept', title: 'Accept', destructive: false },
{ id: 'reject', title: 'Reject', destructive: true },
]);

// Schedule with category
await schedule({
title: 'New Order',
body: 'Order #123 received',
category: 'order',
data: { orderId: '123' },
});

Notification Center

import { useNotifications, NotificationList } from '@54vie/push';

function NotificationScreen() {
const {
notifications,
unreadCount,
markAsRead,
markAllAsRead,
deleteNotification,
clear,
} = useNotifications();

return (
<View>
<Header>
<Text>Notifications ({unreadCount})</Text>
<Button onPress={markAllAsRead}>Mark all read</Button>
</Header>

<NotificationList
notifications={notifications}
onPress={(n) => {
markAsRead(n.id);
handleNavigation(n.data);
}}
onDelete={(n) => deleteNotification(n.id)}
/>
</View>
);
}

Badge Management

import { pushService } from '@54vie/push';

// Set badge count
await pushService.setBadgeCount(5);

// Clear badge
await pushService.clearBadge();

Notification Channels (Android)

import { NotificationChannel } from '@54vie/push';

// Create channels (call at app start)
await NotificationChannel.create({
id: 'payments',
name: 'Payment Notifications',
importance: 'high',
sound: 'payment_sound',
vibration: true,
});

await NotificationChannel.create({
id: 'promotions',
name: 'Promotions',
importance: 'default',
});

Deep Linking

import { DeepLinkRouter } from '@54vie/push';

// Register routes
DeepLinkRouter.register('order/:orderId', ({ orderId }) => {
navigation.navigate('OrderDetail', { id: orderId });
});

DeepLinkRouter.register('miniapp/:appId', ({ appId }) => {
navigation.navigate('MiniProgram', { appId });
});

// Handle notification tap
onNotificationOpened((notification) => {
if (notification.data?.deepLink) {
DeepLinkRouter.navigate(notification.data.deepLink);
}
});

Components

import { NotificationBadge, NotificationItem } from '@54vie/push';

// Badge with count
<NotificationBadge>
<Icon name="bell" />
</NotificationBadge>

// Notification item
<NotificationItem
notification={notification}
onPress={() => handlePress(notification)}
onDelete={() => handleDelete(notification.id)}
/>