* wip * wip * wip * format * wip(mobile): lint and format * cleanup * nits * nits * idiomatic react * nit * format all root files
94 lines
2.7 KiB
TypeScript
94 lines
2.7 KiB
TypeScript
import { useState } from 'react';
|
|
import { Pressable, Text, TextInput, View } from 'react-native';
|
|
import { toast } from 'sonner-native';
|
|
import { cn } from '@/lib/utils';
|
|
import { toUserMessage } from '@/lib/errors';
|
|
import { editTextParticleContent } from '@/lib/firestore-particles';
|
|
import { particlePath, toFirestoreDocPath } from '@/lib/particle-path';
|
|
import { useSuspendPlayback } from '@/hooks/use-suspend-playback';
|
|
import { BottomSheet } from '@/components/BottomSheet';
|
|
|
|
interface EditParticleSheetProps {
|
|
open: boolean;
|
|
onClose: () => void;
|
|
networkId: string;
|
|
streamId: string;
|
|
particleId: string;
|
|
currentContent: string;
|
|
}
|
|
|
|
export function EditParticleSheet({
|
|
open,
|
|
onClose,
|
|
networkId,
|
|
streamId,
|
|
particleId,
|
|
currentContent,
|
|
}: EditParticleSheetProps) {
|
|
useSuspendPlayback(open, 'edit-particle');
|
|
|
|
const [content, setContent] = useState(currentContent);
|
|
const [saving, setSaving] = useState(false);
|
|
|
|
// Reset the editor each time the sheet opens fresh.
|
|
const [prevOpen, setPrevOpen] = useState(open);
|
|
if (open !== prevOpen) {
|
|
setPrevOpen(open);
|
|
if (open) {
|
|
setContent(currentContent);
|
|
setSaving(false);
|
|
}
|
|
}
|
|
|
|
const trimmed = content.trim();
|
|
const canSave = !saving && trimmed.length > 0 && trimmed !== currentContent;
|
|
|
|
const handleSave = async () => {
|
|
if (!canSave) return;
|
|
setSaving(true);
|
|
try {
|
|
const docPath = toFirestoreDocPath(
|
|
particlePath(networkId, [streamId, particleId]),
|
|
);
|
|
await editTextParticleContent(docPath, trimmed);
|
|
onClose();
|
|
} catch (err) {
|
|
toast.error(toUserMessage(err));
|
|
setSaving(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<BottomSheet open={open} onClose={onClose} avoidKeyboard>
|
|
<View className="flex-row items-center justify-between px-5 pb-3">
|
|
<Pressable onPress={onClose} hitSlop={12}>
|
|
<Text className="text-white/70 text-base">Cancel</Text>
|
|
</Pressable>
|
|
<Text className="text-white text-base font-semibold">Edit</Text>
|
|
<Pressable onPress={handleSave} disabled={!canSave} hitSlop={12}>
|
|
<Text
|
|
className={cn(
|
|
'text-base font-semibold',
|
|
canSave ? 'text-white' : 'text-white/30',
|
|
)}
|
|
>
|
|
{saving ? 'Saving...' : 'Save'}
|
|
</Text>
|
|
</Pressable>
|
|
</View>
|
|
<View className="px-5 pb-6">
|
|
<TextInput
|
|
value={content}
|
|
onChangeText={setContent}
|
|
autoFocus
|
|
multiline
|
|
placeholder="Message"
|
|
placeholderTextColor="rgba(255,255,255,0.3)"
|
|
className="bg-white/10 rounded-xl px-4 py-3 text-white text-lg min-h-[120px]"
|
|
textAlignVertical="top"
|
|
/>
|
|
</View>
|
|
</BottomSheet>
|
|
);
|
|
}
|