fix: dock app badge shows incorrect number

Closes #122

We now only show number based on open streams
This commit is contained in:
talksik
2026-04-09 12:31:14 -07:00
parent d024751135
commit 6fe5af8d8d
4 changed files with 47 additions and 13 deletions
+4
View File
@@ -18,6 +18,7 @@ import { particlePath } from "@/lib/particle-path";
import { useParticle } from "@/hooks/use-particle";
import type { Particle } from "@/api/types";
import { PropsWithChildren, useCallback } from "react";
import { useDockBadge } from "@/hooks/use-dock-badge";
import { toast } from "sonner";
function getParticleDisplayName(particle: Particle): string {
@@ -170,6 +171,9 @@ function TopBar() {
}
export default function Layout({ children }: PropsWithChildren) {
const { networkId } = useParams();
useDockBadge(networkId);
return (
<div className="flex h-screen flex-col">
<TopBar />
-4
View File
@@ -8,8 +8,6 @@ import { ComposeOverlay } from "./compose/compose-overlay";
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { useStreamParticles } from "@/hooks/use-stream-particles";
import { useStreamKeyboardNav } from "@/hooks/use-stream-keyboard-nav";
import { useDockBadge } from "@/hooks/use-dock-badge";
import { useAuthStore } from "@/stores/auth-store";
/**
* Route-level component for /:networkId (index).
@@ -21,8 +19,6 @@ export default function NetworkRoot() {
const path = particlePath(networkId!, []);
const { streams, isLoading } = useStreamParticles(path);
const userId = useAuthStore((s) => s.user?.id);
useDockBadge(streams, userId);
const [composeActive, setComposeActive] = useState(false);
const [statusTab, setStatusTab] = useState<"open" | "closed">("open");
+36 -8
View File
@@ -1,24 +1,52 @@
import { useEffect, useMemo } from "react";
import { where } from "firebase/firestore";
import { useLiveParticleChildren } from "@/hooks/use-particle";
import { useAuthStore } from "@/stores/auth-store";
import { particlePath } from "@/lib/particle-path";
import type { Particle, StreamProperties } from "@/api/types";
type StreamParticle = Particle & { type: "stream"; properties: StreamProperties };
const openStatusFilter = where("status", "==", "open");
/**
* Syncs the macOS dock badge with the count of unseen streams.
* Both last_child_created_at and playback_markers store the child particle's
* created_at, so they're directly comparable.
* Self-contained hook that syncs the macOS dock badge with the count of
* unseen open streams the current user is involved in.
*
* Sets up its own Firestore listener so it works independently of
* whatever stream list is rendered on screen.
*/
export function useDockBadge(streams: StreamParticle[], userId: string | undefined) {
export function useDockBadge(networkId: string | undefined) {
const user = useAuthStore((s) => s.user);
const userId = user?.id;
const visibilityScopes = useMemo(() => {
const scopes: string[] = [];
if (userId) scopes.push(`human:${userId}`);
if (networkId) scopes.push(`network:${networkId}`);
return scopes;
}, [userId, networkId]);
const path = networkId ? particlePath(networkId, []) : undefined;
const { children } = useLiveParticleChildren(path, {
orderByField: "last_child_created_at",
orderDirection: "desc",
visibilityScopes,
whereFilter: openStatusFilter,
});
const unseenCount = useMemo(() => {
if (!userId) return 0;
return streams.filter((s) => {
const lastActivity = s.last_child_created_at?.getTime();
return children.filter((c): c is StreamParticle => {
if (c.type !== "stream") return false;
const lastActivity = c.last_child_created_at?.getTime();
if (!lastActivity) return false;
const marker = s.playback_markers?.[userId]?.getTime();
const marker = c.playback_markers?.[userId]?.getTime();
if (marker === undefined) return false;
return lastActivity > marker;
}).length;
}, [streams, userId]);
}, [children, userId]);
useEffect(() => {
window.electronApp.setDockBadge(unseenCount);
+7 -1
View File
@@ -66,7 +66,7 @@ interface UseLiveParticleChildrenParams {
}
export function useLiveParticleChildren(
path: ParticlePath,
path: ParticlePath | undefined,
{
orderByField = "created_at",
orderDirection = "desc",
@@ -81,6 +81,12 @@ export function useLiveParticleChildren(
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
if (!path) {
setChildren([]);
setIsLoading(false);
return;
}
setIsLoading(true);
setError(null);
setChildren([]);