diff --git a/js/src/features/particles/particle-list-view.tsx b/js/src/features/particles/particle-list-view.tsx index 987eb29..3f1a495 100644 --- a/js/src/features/particles/particle-list-view.tsx +++ b/js/src/features/particles/particle-list-view.tsx @@ -197,6 +197,23 @@ function StreamRow({ ); } +// Generates the scopes for filtering particles to those that the user has access to +function useVisibilityScopes( + userEmail?: string, + networkId?: string, +) { + return useMemo(() => { + let scopes: string[] = []; + if (userEmail) { + scopes.push(`human:${userEmail}`); + } + if (networkId) { + scopes.push(`network:${networkId}`); + } + return scopes; + }, [userEmail, networkId]); +} + interface ParticleListViewProps { path: ParticlePath; } @@ -205,8 +222,11 @@ interface ParticleListViewProps { * List of stream particles for a container (network root, folder, etc.). */ export function ParticleListView({ path }: ParticleListViewProps) { - const { children, isLoading } = useLiveParticleChildren(path, "last_child_created_at", "desc"); const { networkId } = parseParticlePath(path); + const user = useAuthStore((s) => s.user); + const visibilityScopes = useVisibilityScopes(user?.email, networkId); + + const { children, isLoading } = useLiveParticleChildren(path, "last_child_created_at", "desc", visibilityScopes); const navigate = useNavigate(); const streams = useMemo( diff --git a/js/src/hooks/use-particle.ts b/js/src/hooks/use-particle.ts index 6d17f61..620b56c 100644 --- a/js/src/hooks/use-particle.ts +++ b/js/src/hooks/use-particle.ts @@ -59,6 +59,7 @@ export function useLiveParticleChildren( path: ParticlePath, orderByField: string = "created_at", orderDirection: "asc" | "desc" = "desc", + visibilityScopes?: string[], ): UseLiveParticleChildrenResult { const [children, setChildren] = useState([]); const [isLoading, setIsLoading] = useState(true); @@ -81,6 +82,7 @@ export function useLiveParticleChildren( setError(err); setIsLoading(false); }, + visibilityScopes, orderByField, orderDirection, ); diff --git a/js/src/lib/firestore-particles.ts b/js/src/lib/firestore-particles.ts index 4e51642..628d561 100644 --- a/js/src/lib/firestore-particles.ts +++ b/js/src/lib/firestore-particles.ts @@ -9,6 +9,7 @@ import { orderBy, limit, serverTimestamp, + where, Timestamp, type DocumentData, type FirestoreDataConverter, @@ -128,10 +129,17 @@ export function subscribeToParticleChildren( collectionPath: string, onData: (children: Particle[]) => void, onError: (error: Error) => void, + visibilityScopes: string[] = [], orderByField: string = "created_at", orderDirection: "asc" | "desc" = "desc", ): Unsubscribe { - const q = query(typedCollection(collectionPath), orderBy(orderByField, orderDirection)); + let q = query(typedCollection(collectionPath), orderBy(orderByField, orderDirection)); + if (visibilityScopes.length > 0) { + q = query( + q, + where("visible_to", "array-contains-any", visibilityScopes), + ); + } return onSnapshot( q, (snap) => {