First commit
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
import * as Notifications from 'expo-notifications';
|
||||
import Constants from 'expo-constants';
|
||||
import { pb } from './pocketbase';
|
||||
import { getOrCreateDeviceId } from './household';
|
||||
|
||||
Notifications.setNotificationHandler({
|
||||
handleNotification: async () => ({
|
||||
shouldShowAlert: true,
|
||||
shouldPlaySound: true,
|
||||
shouldSetBadge: false,
|
||||
shouldShowBanner: true,
|
||||
shouldShowList: true,
|
||||
}),
|
||||
});
|
||||
|
||||
export async function requestNotificationPermission(): Promise<boolean> {
|
||||
const { status } = await Notifications.requestPermissionsAsync();
|
||||
return status === 'granted';
|
||||
}
|
||||
|
||||
export async function getFcmToken(): Promise<string | null> {
|
||||
try {
|
||||
const projectId =
|
||||
Constants.expoConfig?.extra?.eas?.projectId ??
|
||||
(Constants as any).easConfig?.projectId;
|
||||
const token = await Notifications.getExpoPushTokenAsync(
|
||||
projectId ? { projectId } : {}
|
||||
);
|
||||
return token.data;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function updateFcmToken(householdId: string, enabled: boolean): Promise<void> {
|
||||
const deviceId = await getOrCreateDeviceId();
|
||||
const token = enabled ? await getFcmToken() : null;
|
||||
|
||||
const existing = await pb.collection('members').getFullList({
|
||||
filter: `device_id = "${deviceId}" && household = "${householdId}"`,
|
||||
});
|
||||
if (existing.length === 0) return;
|
||||
|
||||
await pb.collection('members').update(existing[0].id, {
|
||||
fcm_token: token,
|
||||
notifications_enabled: enabled,
|
||||
});
|
||||
}
|
||||
|
||||
export async function sendShoppingListPush(
|
||||
householdId: string,
|
||||
itemName: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
const deviceId = await getOrCreateDeviceId();
|
||||
const members = await pb.collection('members').getFullList({
|
||||
filter: `household = "${householdId}" && notifications_enabled = true && fcm_token != ""`,
|
||||
});
|
||||
const tokens = members
|
||||
.filter((m) => m.device_id !== deviceId)
|
||||
.map((m) => m.fcm_token as string)
|
||||
.filter((t) => t?.startsWith('ExponentPushToken'));
|
||||
|
||||
if (tokens.length === 0) return;
|
||||
|
||||
await fetch('https://exp.host/--/api/v2/push/send', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
|
||||
body: JSON.stringify(
|
||||
tokens.map((to) => ({
|
||||
to,
|
||||
title: 'Einkaufsliste',
|
||||
body: `${itemName} wurde hinzugefügt`,
|
||||
sound: 'default',
|
||||
}))
|
||||
),
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('sendShoppingListPush failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
export async function scheduleExpiryCheck(
|
||||
items: Array<{ name: string; expiryDate: Date | null }>
|
||||
) {
|
||||
await Notifications.cancelAllScheduledNotificationsAsync();
|
||||
|
||||
const now = new Date();
|
||||
const threeDays = 3 * 24 * 60 * 60 * 1000;
|
||||
|
||||
const expiringSoon = items.filter(
|
||||
(item) =>
|
||||
item.expiryDate &&
|
||||
item.expiryDate.getTime() - now.getTime() <= threeDays &&
|
||||
item.expiryDate.getTime() > now.getTime()
|
||||
);
|
||||
|
||||
for (const item of expiringSoon) {
|
||||
await Notifications.scheduleNotificationAsync({
|
||||
content: {
|
||||
title: 'MHD läuft ab',
|
||||
body: `${item.name} läuft in ≤ 3 Tagen ab!`,
|
||||
data: {},
|
||||
},
|
||||
trigger: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user