refactor: reference human id instead of email (#73)
* refactor: update api and client to reference humanIds * fix: prevent deletion of network member This may cause various side effects if there is data in other services which reference this member
This commit was merged in pull request #73.
This commit is contained in:
@@ -30,6 +30,7 @@ import type { Particle, StreamProperties } from "@/api/types";
|
||||
import { useAutoplayStore } from "@/stores/autoplay-store";
|
||||
import { where, Timestamp } from "firebase/firestore";
|
||||
import { RECENCY_WINDOW_HOURS } from "@/lib/constants";
|
||||
import { useNetwork } from "@/hooks/use-networks";
|
||||
|
||||
function getParticleTypeIcon(particle: Particle): LucideIcon {
|
||||
switch (particle.type) {
|
||||
@@ -88,7 +89,7 @@ function StreamRow({
|
||||
const { latestChild } = useLiveLatestChild(streamPath);
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const userId = user?.id ?? "";
|
||||
const userEmail = user?.email ?? "";
|
||||
const network = useNetwork(networkId);
|
||||
|
||||
// Autoplay: trigger only when latestChild *changes* to a new media particle,
|
||||
// not on initial data load. We track the "settled" id — the first non-null value
|
||||
@@ -106,7 +107,7 @@ function StreamRow({
|
||||
if (latestChild.id === settledIdRef.current) return;
|
||||
settledIdRef.current = latestChild.id;
|
||||
|
||||
if (latestChild.created_by_email === userEmail) return;
|
||||
if (latestChild.created_by_human_id === userId) return;
|
||||
|
||||
if (latestChild.type === "text") {
|
||||
new Audio(beepSound).play().catch(() => {});
|
||||
@@ -125,20 +126,22 @@ function StreamRow({
|
||||
const initials = useMemo(() => {
|
||||
if (isDM) {
|
||||
const otherEntry = particle.visible_to.find(
|
||||
(v) => v !== `human:${userEmail}`,
|
||||
(v) => v !== `human:${userId}`,
|
||||
);
|
||||
if (otherEntry) {
|
||||
const otherEmail = otherEntry.replace("human:", "");
|
||||
return getInitials(otherEmail);
|
||||
const otherId = otherEntry.replace("human:", "");
|
||||
const otherHuman = network?.humans?.find((h) => h.id === otherId);
|
||||
if (otherHuman) return getInitials(otherHuman.email);
|
||||
}
|
||||
}
|
||||
|
||||
if (latestChild) {
|
||||
return getInitials(latestChild.created_by_email);
|
||||
const creator = network?.humans?.find((h) => h.id === latestChild.created_by_human_id);
|
||||
if (creator) return getInitials(creator.email);
|
||||
}
|
||||
|
||||
return particle.properties.name.slice(0, 2).toUpperCase();
|
||||
}, [isDM, particle.visible_to, particle.properties.name, userEmail, latestChild]);
|
||||
}, [isDM, particle.visible_to, particle.properties.name, userId, latestChild, network]);
|
||||
|
||||
const isUnseen = useMemo(() => {
|
||||
if (!latestChild) return false;
|
||||
@@ -150,17 +153,17 @@ function StreamRow({
|
||||
|
||||
const senderPrefix = useMemo(() => {
|
||||
if (!latestChild) return null;
|
||||
const isCurrentUser = latestChild.created_by_email === userEmail;
|
||||
const isCurrentUser = latestChild.created_by_human_id === userId;
|
||||
if (isDM) {
|
||||
return isCurrentUser ? "You: " : null;
|
||||
}
|
||||
// Group stream
|
||||
if (isCurrentUser) return "You: ";
|
||||
const emailPrefix = latestChild.created_by_email.split("@")[0];
|
||||
const capitalized =
|
||||
emailPrefix.charAt(0).toUpperCase() + emailPrefix.slice(1);
|
||||
const creator = network?.humans?.find((h) => h.id === latestChild.created_by_human_id);
|
||||
const name = creator?.email_prefix ?? latestChild.created_by_human_id;
|
||||
const capitalized = name.charAt(0).toUpperCase() + name.slice(1);
|
||||
return `${capitalized}: `;
|
||||
}, [latestChild, userEmail, isDM]);
|
||||
}, [latestChild, userId, isDM, network]);
|
||||
|
||||
const subtitle = latestChild
|
||||
? getMessagePreview(latestChild)
|
||||
@@ -237,19 +240,19 @@ function StreamRow({
|
||||
|
||||
// Generates the scopes for filtering particles to those that the user has access to
|
||||
function useVisibilityScopes(
|
||||
userEmail?: string,
|
||||
userId?: string,
|
||||
networkId?: string,
|
||||
) {
|
||||
return useMemo(() => {
|
||||
let scopes: string[] = [];
|
||||
if (userEmail) {
|
||||
scopes.push(`human:${userEmail}`);
|
||||
if (userId) {
|
||||
scopes.push(`human:${userId}`);
|
||||
}
|
||||
if (networkId) {
|
||||
scopes.push(`network:${networkId}`);
|
||||
}
|
||||
return scopes;
|
||||
}, [userEmail, networkId]);
|
||||
}, [userId, networkId]);
|
||||
}
|
||||
|
||||
interface ParticleListViewProps {
|
||||
@@ -262,7 +265,7 @@ interface ParticleListViewProps {
|
||||
export function ParticleListView({ path }: ParticleListViewProps) {
|
||||
const { networkId } = parseParticlePath(path);
|
||||
const user = useAuthStore((s) => s.user);
|
||||
const visibilityScopes = useVisibilityScopes(user?.email, networkId);
|
||||
const visibilityScopes = useVisibilityScopes(user?.id, networkId);
|
||||
|
||||
const [recencyCutoff, setRecencyCutoff] = useState(() => {
|
||||
const d = new Date();
|
||||
|
||||
Reference in New Issue
Block a user