fix: prevent nesting of formatted text reactions
Usage of map was causing issues if the text reaction had special characters. Closes #205
This commit is contained in:
@@ -33,6 +33,7 @@ import Animated, {
|
||||
import { REACTION_EMOJIS, type Reactions } from "@/api/types";
|
||||
import type { Human } from "@/api/types";
|
||||
import { resolveHumanDisplay } from "@/lib/humans";
|
||||
import { sanitizeReactionText } from "@/lib/firestore-particles";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useSuspendPlayback } from "@/hooks/use-suspend-playback";
|
||||
|
||||
@@ -327,7 +328,9 @@ export function ReactionSheet({
|
||||
<View className="flex-1 bg-white/10 rounded-full px-4 py-2.5">
|
||||
<TextInput
|
||||
value={text}
|
||||
onChangeText={(v) => setText(v.slice(0, TEXT_REACTION_MAX))}
|
||||
onChangeText={(v) =>
|
||||
setText(sanitizeReactionText(v).slice(0, TEXT_REACTION_MAX))
|
||||
}
|
||||
placeholder="Send a quick reply..."
|
||||
placeholderTextColor="rgba(255,255,255,0.4)"
|
||||
maxLength={TEXT_REACTION_MAX}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Timestamp,
|
||||
arrayUnion,
|
||||
arrayRemove,
|
||||
FieldPath,
|
||||
type DocumentData,
|
||||
type FirestoreDataConverter,
|
||||
type QueryDocumentSnapshot,
|
||||
@@ -419,17 +420,30 @@ export async function updateStreamPlaybackMarker(
|
||||
});
|
||||
}
|
||||
|
||||
// Strip characters that Firestore's dotted field-path syntax treats specially.
|
||||
// Using FieldPath bypasses the parser, but we also forbid these in stored keys
|
||||
// so reaction maps stay portable across any future read path.
|
||||
const RESERVED_REACTION_CHARS = /[~*/[\]]/g;
|
||||
|
||||
export function sanitizeReactionText(text: string): string {
|
||||
return text.replace(RESERVED_REACTION_CHARS, "");
|
||||
}
|
||||
|
||||
export async function toggleParticleReaction(
|
||||
docPath: string,
|
||||
emoji: string,
|
||||
humanId: string,
|
||||
currentReactions?: Reactions,
|
||||
): Promise<void> {
|
||||
const key = sanitizeReactionText(emoji);
|
||||
if (!key) return;
|
||||
const particleRef = typedDoc(docPath);
|
||||
const field = `reactions.${emoji}`;
|
||||
const alreadyReacted = currentReactions?.[emoji]?.includes(humanId) ?? false;
|
||||
await updateDoc(particleRef, {
|
||||
[field]: alreadyReacted ? arrayRemove(humanId) : arrayUnion(humanId),
|
||||
updated_at: serverTimestamp(),
|
||||
});
|
||||
const alreadyReacted = currentReactions?.[key]?.includes(humanId) ?? false;
|
||||
await updateDoc(
|
||||
particleRef,
|
||||
new FieldPath("reactions", key),
|
||||
alreadyReacted ? arrayRemove(humanId) : arrayUnion(humanId),
|
||||
"updated_at",
|
||||
serverTimestamp(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user