diff --git a/mobile/app/(app)/(tabs)/_layout.tsx b/mobile/app/(app)/(tabs)/_layout.tsx
index 8e70fe5..5318c99 100644
--- a/mobile/app/(app)/(tabs)/_layout.tsx
+++ b/mobile/app/(app)/(tabs)/_layout.tsx
@@ -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 (
router.push("/messages")} hitSlop={8} style={styles.headerButton}>
-
+
+
+
+
);
}
@@ -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 (
- {count > 0 && (
-
- {count > 9 ? "9+" : count}
-
- )}
+
+
+ );
+}
+
+function UnreadBadge({ count, styles }: { count: number; styles: ReturnType }) {
+ if (count <= 0) return null;
+ return (
+
+ {count > 9 ? "9+" : count}
);
}