'use client'; import { useState, useRef, useEffect } from 'react'; import { Button } from '../ui/button'; import { Textarea } from '../ui/textarea'; import { Paperclip, Send, Smile, Mic, Sparkles, X, CornerDownLeft } from 'lucide-react'; import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover'; import { CSSTransition } from 'react-transition-group'; import { VoiceRecorder } from '../voice-recorder'; import type { ReplyTo, Message, Group } from '@/lib/types'; import { useAppContext } from '@/contexts/app-context'; import { cn } from '@/lib/utils'; import { Skeleton } from '../ui/skeleton'; import Picker from '@emoji-mart/react'; import data from '@emoji-mart/data'; interface MessageInputProps { chatId: string | null; disabled?: boolean; lastMessage: Message | null; isGroupChat?: boolean; currentGroup?: Group; onGetSuggestedReplies: (message: Message) => Promise; sendTextMessage: (text: string, replyTo?: ReplyTo | null) => void; onSelectMedia: (file: File) => void; onSendAudio: (data: { file: File, duration: number }) => void; } const QuotedMessagePreview = ({ replyTo, onCancel }: { replyTo: ReplyTo | null, onCancel: () => void }) => (
{replyTo && ( <>

{replyTo.displayName}

{replyTo.text || (replyTo.imageKey ? 'Image' : replyTo.videoKey ? 'Video' : 'Voice Message')}

)}
); export function MessageInput({ sendTextMessage, onSelectMedia, onSendAudio, chatId, disabled, lastMessage, onGetSuggestedReplies, isGroupChat, currentGroup, }: MessageInputProps) { const { currentUser, setUserTyping, replyTo, setReplyTo, playSound, t } = useAppContext(); const [message, setMessage] = useState(''); const [isRecording, setIsRecording] = useState(false); const [suggestedReplies, setSuggestedReplies] = useState([]); const [showSuggestions, setShowSuggestions] = useState(false); const textareaRef = useRef(null); const typingTimeoutRef = useRef(null); const handleSend = () => { if (message.trim() || isRecording) { playSound('send'); if (message.trim()) { sendTextMessage(message, replyTo); } setMessage(''); setReplyTo(null); if (textareaRef.current) { textareaRef.current.style.height = '40px'; } } }; useEffect(() => { const fetchSuggestions = async () => { if (lastMessage && lastMessage.sender !== currentUser?.uid && lastMessage.text) { setShowSuggestions(true); setSuggestedReplies([]); // Clear old suggestions immediately const replies = await onGetSuggestedReplies(lastMessage); setSuggestedReplies(replies); } else { setShowSuggestions(false); setSuggestedReplies([]); } }; // Only fetch suggestions if the last message changes if (lastMessage?.id) { fetchSuggestions(); } }, [lastMessage?.id, lastMessage?.sender, lastMessage?.text, currentUser?.uid, onGetSuggestedReplies]); const handleInputChange = (e: React.ChangeEvent) => { setMessage(e.target.value); if (textareaRef.current) { textareaRef.current.style.height = 'auto'; textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`; } if (chatId) { if (typingTimeoutRef.current) clearTimeout(typingTimeoutRef.current); else setUserTyping(chatId, true); typingTimeoutRef.current = setTimeout(() => { setUserTyping(chatId, false); typingTimeoutRef.current = null; }, 2000); } }; const handleSendSuggestion = (reply: string) => { sendTextMessage(reply, null); setShowSuggestions(false); } const handleKeyPress = (event: React.KeyboardEvent) => { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); handleSend(); } }; const handleFileSelect = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (file) { onSelectMedia(file); } // Reset the input value to allow selecting the same file again e.target.value = ''; }; const handleEmojiSelect = (emoji: any) => { setMessage(prev => prev + emoji.native); }; if (disabled) { return (
{t('messagingDisabled')}
); } const sendingMode = currentGroup?.info?.settings?.sendingMode || 'everyone'; const isMuted = isGroupChat && currentGroup?.info.mutedMembers?.[currentUser?.uid || '']; const canSend = !isGroupChat || ( (sendingMode === 'everyone' && !isMuted) || (sendingMode === 'admins' && currentGroup?.admins[currentUser?.uid || '']) || (sendingMode === 'owner' && currentGroup?.info.createdBy === currentUser?.uid) ); if (!canSend) { return (

{isMuted ? t('youAreMuted') : t('adminsCanSend')}

); } if (isRecording) { return setIsRecording(false)} onSend={onSendAudio} />; } return (
setReplyTo(null)} /> {showSuggestions && (
{suggestedReplies.length > 0 ? ( suggestedReplies.map((reply, i) => ( )) ) : ( Array.from({ length: 3 }).map((_, i) => ) )}
)}