feat(mobile): Badge fuer ungelesene Nachrichten an der Sprechblase

found.md (iOS-Feedback): Push kam an, aber die Sprechblase zeigte nichts.
MessagesHeaderButton zeigt jetzt conversations.unreadCount im selben Badge
wie die Glocke (gemeinsame UnreadBadge-Komponente), aktualisiert alle 30 s;
Lesen eines Chats invalidiert den Zaehler bereits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-10-04 15:01:51 +02:00
1 parent 361aba0d1d
commit 2bd4b2d973
1 file changed
+26 -7
+26 -7
View File
@@ -152,13 +152,28 @@ function SettingsHeaderButton() {
);
}
// found.md: a push for a new message arrived but the speech bubble showed
// nothing. Polling keeps the badge current while the app stays open; reading
// a conversation invalidates conversations.* (see messages/[conversationId]).
const UNREAD_MESSAGES_POLL_MS = 30 * 1000;
function MessagesHeaderButton() {
const router = useRouter();
const trpc = useTRPC();
const { activePetId } = useActivePet();
const { colors } = useTheme();
const styles = useMemo(() => makeStyles(colors), [colors]);
const { data } = useQuery({
...trpc.conversations.unreadCount.queryOptions({ petId: activePetId ?? "" }),
enabled: !!activePetId,
refetchInterval: UNREAD_MESSAGES_POLL_MS,
});
return (
<Pressable onPress={() => router.push("/messages")} hitSlop={8} style={styles.headerButton}>
<MessageCircle color={colors.ink} size={22} />
<View>
<MessageCircle color={colors.ink} size={22} />
<UnreadBadge count={data?.count ?? 0} styles={styles} />
</View>
</Pressable>
);
}
@@ -172,16 +187,20 @@ function NotificationsTabIcon({ color, size }: { color: ColorValue; size: number
...trpc.notifications.unreadCount.queryOptions({ petId: activePetId ?? "" }),
enabled: !!activePetId,
});
const count = data?.count ?? 0;
return (
<View>
<Bell color={color} size={size} />
{count > 0 && (
<View style={styles.badge}>
<Text style={styles.badgeText}>{count > 9 ? "9+" : count}</Text>
</View>
)}
<UnreadBadge count={data?.count ?? 0} styles={styles} />
</View>
);
}
function UnreadBadge({ count, styles }: { count: number; styles: ReturnType<typeof makeStyles> }) {
if (count <= 0) return null;
return (
<View style={styles.badge}>
<Text style={styles.badgeText}>{count > 9 ? "9+" : count}</Text>
</View>
);
}