"use client"; import React, { createContext, useContext, useState, useCallback } from 'react'; import { ref, update, remove, set } from "firebase/database"; import { storageService } from '@/lib/storage-service'; import type { User, ReplyTo, PrivacySettings, DataMode, ChatRecipient } from '@/lib/types'; import { useAuth } from '@/contexts/auth-context'; import { useFirebase } from '@/contexts/firebase-context'; import { useSettings } from '@/contexts/settings-context'; import { Capacitor } from '@capacitor/core'; export const useChatUtilsCore = () => { const { currentUser } = useAuth(); const { rtdb } = useFirebase(); const { addToast, t, dataMode, privacySettings } = useSettings(); const clearChatHistory = useCallback(async (chatId: string) => { try { await storageService.clearMessages(chatId); addToast(t('historyCleared')); window.dispatchEvent(new CustomEvent('localDataChange', { detail: { chatId } })); } catch (error) { console.error("Error clearing local chat history:", error); addToast(t('historyClearError'), { variant: "destructive" }); } }, [addToast, t]); const deleteMessage = useCallback(async (chatId: string, messageId: string) => { if (!currentUser) return; try { const messageRef = ref(rtdb, `chats/${chatId}/messages/${messageId}`); const updatePayload = { text: null, encryptedText: null, isDeleted: true, audioKey: null, imageKey: null, videoKey: null, replyTo: null, transcription: null, urlPreviewData: null, compressedText: null, reactions: null, }; await update(messageRef, updatePayload); await storageService.updateMessage(chatId, messageId, { ...updatePayload, isDeleted: true }); window.dispatchEvent(new CustomEvent('localDataChange', { detail: { chatId } })); } catch (error) { console.error("Error deleting message:", error); addToast(t('deleteMessageError'), { variant: "destructive" }); } }, [currentUser, addToast, rtdb, t]); const setUserTyping = useCallback((chatId: string, isTyping: boolean) => { if (!currentUser || dataMode === 'ultra' || !privacySettings.showTyping) return; const typingRef = ref(rtdb, `typing/${chatId}/${currentUser.uid}`); if (isTyping) { set(typingRef, currentUser.displayName); } else { remove(typingRef); } }, [currentUser, dataMode, rtdb, privacySettings.showTyping]); const uploadFile = useCallback(async (file: File, onProgress: (progress: number) => void) => { const formData = new FormData(); formData.append('file', file); return new Promise<{ fileKey: string }>((resolve, reject) => { const xhr = new XMLHttpRequest(); const isNative = Capacitor.isNativePlatform(); const baseUrl = isNative ? process.env.NEXT_PUBLIC_API_BASE_URL : ''; const uploadUrl = `${baseUrl}/api/media`; xhr.open('POST', uploadUrl, true); xhr.upload.onprogress = (event) => { if (event.lengthComputable) { const progress = (event.loaded / event.total) * 100; onProgress(progress); } }; xhr.onload = () => { if (xhr.status >= 200 && xhr.status < 300) { try { const response = JSON.parse(xhr.responseText); resolve({ fileKey: response.fileKey }); } catch (e) { reject(new Error('Invalid JSON response from server.')); } } else { reject(new Error(`Upload failed: ${xhr.statusText}`)); } }; xhr.onerror = () => { reject(new Error('Upload failed due to a network error.')); }; xhr.send(formData); }); }, []); const transcribeAndSet = useCallback(async (messageId: string, audioFile: File, recipient: ChatRecipient) => { if (!currentUser) return; const chatId = recipient.isGroup ? recipient.uid : (currentUser.uid < recipient.uid ? `private_'''${currentUser.uid}'''_'''${recipient.uid}'''` : `private_'''${recipient.uid}'''_'''${currentUser.uid}'''`); if (!chatId) return; try { // Disabled } catch (error) { console.warn("Could not transcribe audio:", error); } }, [currentUser, rtdb]); return { clearChatHistory, deleteMessage, setUserTyping, uploadFile, transcribeAndSet, }; }; type ChatUtilsContextType = ReturnType; const ChatUtilsContext = createContext(null); export const useChatUtils = () => { const context = useContext(ChatUtilsContext); if (!context) { throw new Error('useChatUtils must be used within a ChatUtilsProvider'); } return context; }; export const ChatUtilsProvider = ({ children }: { children: React.ReactNode }) => { const chatUtilsData = useChatUtilsCore(); return ( {children} ); };