refactor: use interfaces for function params

This commit is contained in:
talksik
2026-04-07 14:21:34 -07:00
parent 4a9cb7fc58
commit e7384cb45c
4 changed files with 76 additions and 70 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ interface FolderViewProps {
}
export function FolderView({ path, folderParticle }: FolderViewProps) {
const { children, error, isLoading } = useLiveParticleChildren(path);
const { children, error, isLoading } = useLiveParticleChildren({ path });
const { networkId } = parseParticlePath(path);
return (
+39 -28
View File
@@ -1,4 +1,4 @@
import { useState, useEffect, useMemo } from "react";
import { useState, useEffect } from "react";
import {
subscribeToParticle,
subscribeToParticleChildren,
@@ -26,13 +26,12 @@ export function useLiveParticle(path: ParticlePath): UseLiveParticleResult {
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const docPath = useMemo(() => toFirestoreDocPath(path), [path]);
useEffect(() => {
setIsLoading(true);
setError(null);
setParticle(null);
const docPath = toFirestoreDocPath(path);
const unsubscribe = subscribeToParticle(
docPath,
(data) => {
@@ -46,7 +45,7 @@ export function useLiveParticle(path: ParticlePath): UseLiveParticleResult {
);
return unsubscribe;
}, [docPath]);
}, [path]);
return { particle, isLoading, error };
}
@@ -57,47 +56,59 @@ interface UseLiveParticleChildrenResult {
error: Error | null;
}
interface UseLiveParticleChildrenParams {
orderByField?: string;
orderDirection?: "asc" | "desc";
visibilityScopes?: string[];
onAdded?: (child: Particle) => void;
onRemoved?: (child: Particle, updatedChildren: Particle[]) => void;
whereFilter?: QueryFieldFilterConstraint;
}
export function useLiveParticleChildren(
path: ParticlePath,
orderByField: string = "created_at",
orderDirection: "asc" | "desc" = "desc",
visibilityScopes?: string[],
onAdded?: (child: Particle) => void,
onRemoved?: (child: Particle, updatedChildren: Particle[]) => void,
whereFilter?: QueryFieldFilterConstraint
{
orderByField = "created_at",
orderDirection = "desc",
visibilityScopes,
onAdded,
onRemoved,
whereFilter,
}: UseLiveParticleChildrenParams
): UseLiveParticleChildrenResult {
const [children, setChildren] = useState<Particle[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
const collectionPath = useMemo(() => toFirestoreChildrenPath(path), [path]);
useEffect(() => {
setIsLoading(true);
setError(null);
setChildren([]);
const collectionPath = toFirestoreChildrenPath(path);
const unsubscribe = subscribeToParticleChildren(
collectionPath,
(data) => {
setChildren(data);
setIsLoading(false);
},
(err) => {
setError(err);
setIsLoading(false);
},
visibilityScopes,
orderByField,
orderDirection,
onAdded,
onRemoved,
whereFilter,
{
onData: (data) => {
setChildren(data);
setIsLoading(false);
},
onError: (err) => {
setError(err);
setIsLoading(false);
},
visibilityScopes,
orderByField,
orderDirection,
onAdded,
onRemoved,
whereFilter,
}
);
return unsubscribe;
// FIX: do we need to listen to more deps? Would that cause side effects that break behavior
}, [collectionPath]);
}, [path]);
return { children, isLoading, error };
}
+6 -31
View File
@@ -1,10 +1,8 @@
import { useEffect, useMemo, useState } from "react";
import { useMemo } from "react";
import { useLiveParticleChildren } from "@/hooks/use-particle";
import { useAuthStore } from "@/stores/auth-store";
import { parseParticlePath, type ParticlePath } from "@/lib/particle-path";
import type { Particle, StreamProperties } from "@/api/types";
import { where, Timestamp } from "firebase/firestore";
import { useNetwork } from "@/hooks/use-networks";
type StreamParticle = Particle & { type: "stream"; properties: StreamProperties };
@@ -27,37 +25,14 @@ export function useStreamParticles(path: ParticlePath): UseStreamParticlesResult
const { networkId } = parseParticlePath(path);
const user = useAuthStore((s) => s.user);
const visibilityScopes = useVisibilityScopes(user?.id, networkId);
const network = useNetwork(networkId);
const retentionHours = network?.message_retention_hours ?? 24;
const [recencyCutoff, setRecencyCutoff] = useState(() => {
const d = new Date();
d.setHours(d.getHours() - retentionHours);
return Timestamp.fromDate(d);
});
useEffect(() => {
// Recalculate immediately when retention changes
const d = new Date();
d.setHours(d.getHours() - retentionHours);
setRecencyCutoff(Timestamp.fromDate(d));
const interval = setInterval(() => {
const d = new Date();
d.setHours(d.getHours() - retentionHours);
setRecencyCutoff(Timestamp.fromDate(d));
}, 60 * 60 * 1000);
return () => clearInterval(interval);
}, [retentionHours]);
const { children, isLoading } = useLiveParticleChildren(
path,
"last_child_created_at",
"desc",
visibilityScopes,
undefined,
undefined,
where("last_child_created_at", ">=", recencyCutoff),
{
orderByField: "last_child_created_at",
orderDirection: "desc",
visibilityScopes,
}
);
const streams = useMemo(
+30 -10
View File
@@ -128,10 +128,17 @@ export async function getParticle(docPath: string): Promise<Particle | null> {
return doc.data();
}
export interface GetParticleChildrenOptions {
orderByField: string;
orderDirection: "asc" | "desc";
}
export async function getParticleChildren(
collectionPath: string,
orderByField: string = "created_at",
orderDirection: "asc" | "desc" = "asc",
{
orderByField = "created_at",
orderDirection = "asc",
}: GetParticleChildrenOptions = { orderByField: "created_at", orderDirection: "asc" },
): Promise<Particle[]> {
const q = query(
typedCollection(collectionPath),
@@ -141,16 +148,29 @@ export async function getParticleChildren(
return snap.docs.map((d) => d.data());
}
export interface SubscribeToParticleChildrenOptions {
onData: (children: Particle[]) => void;
onError: (error: Error) => void;
visibilityScopes?: string[];
orderByField?: string;
orderDirection?: "asc" | "desc";
onAdded?: (child: Particle) => void;
onRemoved?: (child: Particle, updatedChildren: Particle[]) => void;
whereFilter?: QueryFieldFilterConstraint;
}
export function subscribeToParticleChildren(
collectionPath: string,
onData: (children: Particle[]) => void,
onError: (error: Error) => void,
visibilityScopes: string[] = [],
orderByField: string = "created_at",
orderDirection: "asc" | "desc" = "desc",
onAdded?: (child: Particle) => void,
onRemoved?: (child: Particle, updatedChildren: Particle[]) => void,
whereFilter?: QueryFieldFilterConstraint,
{
onData,
onError,
visibilityScopes = [],
orderByField = "created_at",
orderDirection = "desc",
onAdded,
onRemoved,
whereFilter,
}: SubscribeToParticleChildrenOptions
): Unsubscribe {
let q = query(typedCollection(collectionPath), orderBy(orderByField, orderDirection));
if (visibilityScopes.length > 0) {