correction notifications

This commit is contained in:
2026-05-16 08:33:22 +02:00
parent b02d34453e
commit 43105f6bdc
@@ -1,22 +1,20 @@
import * as Notifications from "expo-notifications";
import { useCallback, useEffect, useRef } from "react"; import { useCallback, useEffect, useRef } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import { usePostiz } from "@/context/PostizContext"; import { usePostiz } from "@/context/PostizContext";
import { PostizPost } from "@/context/PostizContext"; import { PostizPost } from "@/context/PostizContext";
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: true,
shouldShowBanner: true,
shouldShowList: true,
}),
});
const POLL_INTERVAL_MS = 15 * 60 * 1000; const POLL_INTERVAL_MS = 15 * 60 * 1000;
const SEEN_KEY = "postiz_seen_statuses"; const SEEN_KEY = "postiz_seen_statuses";
function isExpoGo(): boolean {
try {
const Constants = require("expo-constants").default;
return Constants?.executionEnvironment === "storeClient";
} catch {
return false;
}
}
async function getSeenStatuses(): Promise<Record<string, string>> { async function getSeenStatuses(): Promise<Record<string, string>> {
try { try {
const { default: AsyncStorage } = await import( const { default: AsyncStorage } = await import(
@@ -39,18 +37,22 @@ async function saveSeenStatuses(map: Record<string, string>) {
} }
async function sendStatusNotification(post: PostizPost) { async function sendStatusNotification(post: PostizPost) {
const isError = post.status === "ERROR"; if (Platform.OS === "web" || isExpoGo()) return;
await Notifications.scheduleNotificationAsync({ try {
content: { const Notifications = require("expo-notifications");
title: isError ? "Post failed to publish" : "Post published!", const isError = post.state === "ERROR";
body: await Notifications.scheduleNotificationAsync({
post.content.length > 80 content: {
? post.content.slice(0, 80) + "…" title: isError ? "Post failed to publish" : "Post published!",
: post.content, body:
data: { postId: post.id }, post.content.length > 80
}, ? post.content.slice(0, 80) + "…"
trigger: null, : post.content,
}); data: { postId: post.id },
},
trigger: null,
});
} catch {}
} }
export function useNotifications() { export function useNotifications() {
@@ -59,57 +61,64 @@ export function useNotifications() {
const permissionGranted = useRef(false); const permissionGranted = useRef(false);
const requestPermissions = useCallback(async () => { const requestPermissions = useCallback(async () => {
if (Platform.OS === "web") return false; if (Platform.OS === "web" || isExpoGo()) return false;
const { status: existing } = await Notifications.getPermissionsAsync(); try {
if (existing === "granted") { const Notifications = require("expo-notifications");
permissionGranted.current = true; Notifications.setNotificationHandler({
return true; handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: true,
shouldShowBanner: true,
shouldShowList: true,
}),
});
const { status: existing } = await Notifications.getPermissionsAsync();
if (existing === "granted") {
permissionGranted.current = true;
return true;
}
const { status } = await Notifications.requestPermissionsAsync();
permissionGranted.current = status === "granted";
return permissionGranted.current;
} catch {
return false;
} }
const { status } = await Notifications.requestPermissionsAsync();
permissionGranted.current = status === "granted";
return permissionGranted.current;
}, []); }, []);
const checkForStatusChanges = useCallback(async () => { const checkForStatusChanges = useCallback(async () => {
if (!client || !permissionGranted.current) return; if (!client || !permissionGranted.current) return;
try { try {
const now = new Date(); const now = new Date();
const from = new Date(now); const from = new Date(now);
from.setDate(from.getDate() - 7); from.setDate(from.getDate() - 7);
const res = await client.get("posts", {
const res = await client.get("/posts", {
params: { params: {
startDate: from.toISOString(), startDate: from.toISOString(),
endDate: now.toISOString(), endDate: now.toISOString(),
}, },
}); });
const posts: PostizPost[] = Array.isArray(res.data) const posts: PostizPost[] = Array.isArray(res.data)
? res.data ? res.data
: res.data?.posts ?? []; : res.data?.posts ?? [];
const seen = await getSeenStatuses(); const seen = await getSeenStatuses();
const updated: Record<string, string> = { ...seen }; const updated: Record<string, string> = { ...seen };
const toNotify: PostizPost[] = []; const toNotify: PostizPost[] = [];
for (const post of posts) { for (const post of posts) {
const prev = seen[post.id]; const prev = seen[post.id];
if (prev === undefined) { if (prev === undefined) {
updated[post.id] = post.status; updated[post.id] = post.state;
continue; continue;
} }
if ( if (
prev !== post.status && prev !== post.state &&
(post.status === "PUBLISHED" || post.status === "ERROR") (post.state === "PUBLISHED" || post.state === "ERROR")
) { ) {
toNotify.push(post); toNotify.push(post);
} }
updated[post.id] = post.status; updated[post.id] = post.state;
} }
await saveSeenStatuses(updated); await saveSeenStatuses(updated);
for (const post of toNotify) { for (const post of toNotify) {
await sendStatusNotification(post); await sendStatusNotification(post);
} }
@@ -117,21 +126,16 @@ export function useNotifications() {
}, [client]); }, [client]);
useEffect(() => { useEffect(() => {
if (!isConfigured || Platform.OS === "web") return; if (!isConfigured || Platform.OS === "web" || isExpoGo()) return;
let mounted = true; let mounted = true;
(async () => { (async () => {
const granted = await requestPermissions(); const granted = await requestPermissions();
if (!granted || !mounted) return; if (!granted || !mounted) return;
await checkForStatusChanges(); await checkForStatusChanges();
intervalRef.current = setInterval(() => { intervalRef.current = setInterval(() => {
checkForStatusChanges(); checkForStatusChanges();
}, POLL_INTERVAL_MS); }, POLL_INTERVAL_MS);
})(); })();
return () => { return () => {
mounted = false; mounted = false;
if (intervalRef.current) { if (intervalRef.current) {