Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 2 additions & 16 deletions src/features/inbox/hooks/useChatMediaSending.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,14 +311,7 @@ export function useChatMediaSending(contactId: string, contactPhone: string | un
toast.error('Erro ao enviar emoji');
}
},
[
ensureInstance,
contactId,
contactPhone,
whatsappConnectionId,
getSafePhone,
updateMessageStatus,
]
[ensureInstance, contactId, whatsappConnectionId, getSafePhone, updateMessageStatus]
);

const handleSendAudioMeme = useCallback(
Expand Down Expand Up @@ -404,14 +397,7 @@ export function useChatMediaSending(contactId: string, contactPhone: string | un
toast.error('Erro ao enviar áudio meme');
}
},
[
ensureInstance,
contactId,
contactPhone,
whatsappConnectionId,
getSafePhone,
updateMessageStatus,
]
[ensureInstance, contactId, whatsappConnectionId, getSafePhone, updateMessageStatus]
);

return {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useAudioManagement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ export function useAudioRecorder(options: UseAudioRecorderOptions = {}) {
});
}
},
[maxDuration, onRecordingComplete]
[maxDuration, onRecordingComplete, setBlobUrl]
);

const pauseRecording = useCallback(() => {
Expand Down
47 changes: 24 additions & 23 deletions src/hooks/useAudioRecorder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ export function useAudioRecorder(options: UseAudioRecorderOptions = {}) {
const [transcription, setTranscription] = useState('');

const mountedRef = useRef(false);
useEffect(() => {
mountedRef.current = true;
return () => {
mountedRef.current = false;
// FIX #9: Cleanup completo em unmount para prevenir memory leaks
cleanupRecordingResources();
if (blobUrlRef.current) {
URL.revokeObjectURL(blobUrlRef.current);
blobUrlRef.current = null;
}
};
}, [cleanupRecordingResources]);

const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const chunksRef = useRef<Blob[]>([]);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const streamRef = useRef<MediaStream | null>(null);
const audioContextRef = useRef<AudioContext | null>(null);
const analyserRef = useRef<AnalyserNode | null>(null);
const animationFrameRef = useRef<number | null>(null);
const recognitionRef = useRef<SpeechRecognition | null>(null);
const lastBlobRef = useRef<Blob | null>(null);
const lastTranscriptionRef = useRef<string>('');
const blobUrlRef = useRef<string | null>(null);

/**
* FIX #9: Libera todos os recursos do recorder (MediaStream, AudioContext,
Expand Down Expand Up @@ -97,17 +97,18 @@ export function useAudioRecorder(options: UseAudioRecorderOptions = {}) {
mediaRecorderRef.current = null;
}, []);

const mediaRecorderRef = useRef<MediaRecorder | null>(null);
const chunksRef = useRef<Blob[]>([]);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const streamRef = useRef<MediaStream | null>(null);
const audioContextRef = useRef<AudioContext | null>(null);
const analyserRef = useRef<AnalyserNode | null>(null);
const animationFrameRef = useRef<number | null>(null);
const recognitionRef = useRef<SpeechRecognition | null>(null);
const lastBlobRef = useRef<Blob | null>(null);
const lastTranscriptionRef = useRef<string>('');
const blobUrlRef = useRef<string | null>(null);
useEffect(() => {
mountedRef.current = true;
return () => {
mountedRef.current = false;
// FIX #9: Cleanup completo em unmount para prevenir memory leaks
cleanupRecordingResources();
if (blobUrlRef.current) {
URL.revokeObjectURL(blobUrlRef.current);
blobUrlRef.current = null;
}
};
}, [cleanupRecordingResources]);

const setBlobUrl = useCallback((url: string | null) => {
if (blobUrlRef.current) {
Expand Down
6 changes: 2 additions & 4 deletions src/hooks/useRealtimeMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ export function useRealtimeMessages() {
{ data: messages, error: messagesError },
] = await Promise.all([
supabase
.schema('evo')
.from('evolution_contacts')
.select('*')
.order('updated_at', { ascending: false })
Expand All @@ -116,7 +115,7 @@ export function useRealtimeMessages() {
if (contactsError) throw contactsError;
if (messagesError) throw messagesError;

const contactList: Contact[] = (contactsRaw as unknown as Contact[] | null) ?? []; // ignore-audit — supabase.schema('evo') absent from generated types; contactsRaw typed as opaque null/unknown
const contactList: Contact[] = (contactsRaw as unknown as Contact[] | null) ?? [];
const messageList: Message[] = messages ?? [];

const contactMap = new Map<string, Contact>();
Expand All @@ -133,13 +132,12 @@ export function useRealtimeMessages() {

if (missingIds.length > 0) {
const { data: extraRaw } = await supabase
.schema('evo')
.from('evolution_contacts')
.select('*')
.in('id', missingIds);
((extraRaw as unknown as Contact[] | null) ?? []).forEach((c: Contact) =>
contactMap.set(c.id, c)
); // ignore-audit — supabase.schema('evo') absent from generated types; extraRaw typed as opaque null/unknown
);
}

if (!isMountedRef.current) return;
Expand Down
7 changes: 2 additions & 5 deletions src/integrations/zappweb/hooks/useZappContactSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,12 @@ export function useZappContactSearch() {
setLoading(true);
const safe = term.replace(/[%_]/g, '');
const { data } = await zappSupabase
.schema('evo')
.from('evolution_contacts')
.select(
`id, push_name, full_name, first_name, last_name, phone_number, email,
company, lead_status, lead_score, tags, profile_picture_url`,
)
.or(
`push_name.ilike.%${safe}%,full_name.ilike.%${safe}%,phone_number.ilike.%${safe}%`,
company, lead_status, lead_score, tags, profile_picture_url`
)
.or(`push_name.ilike.%${safe}%,full_name.ilike.%${safe}%,phone_number.ilike.%${safe}%`)
.limit(20);
setResults((data ?? []) as EvolutionContact[]);
setLoading(false);
Expand Down
66 changes: 65 additions & 1 deletion vercel.json
Original file line number Diff line number Diff line change
@@ -1 +1,65 @@
ewogICJmcmFtZXdvcmsiOiAidml0ZSIsCiAgImJ1aWxkQ29tbWFuZCI6ICJ2aXRlIGJ1aWxkIiwKICAib3V0cHV0RGlyZWN0b3J5IjogImRpc3QiLAogICJpbnN0YWxsQ29tbWFuZCI6ICJidW4gaW5zdGFsbCIsCiAgImVudiI6IHsKICAgICJWSVRFX1NVUEFCQVNFX1VSTCI6ICJodHRwczovL3N1cGFiYXNlLmF0b21pY2Fici5jb20uYnIiLAogICAgIlZJVEVfU1VQQUJBU0VfQU5PTl9LRVkiOiAiZXlKaGJHY2lPaUpJVXpJMU5pSXNJblI1Y0NJNklrcFhWQ0o5LmV3b2dJQ0p5YjJ4bElqb2dJbUZ1YjI0aUxBb2dJQ0pwYzNNaU9pQWljM1Z3WVdKaGMyVWlMQW9nSUNKcFlYUWlPaUF4TnpFMU1EVXdPREF3TEFvZ0lDSmxlSEFpT2lBeE9EY3lPREUzTWpBd0NuMC5ydmFtYzBYSHVTQ1lCMWdsQndPQ0N4Z2ZkOXl4V1ZZTG5oRnpnNS03VFJrIiwKICAgICJWSVRFX0FQUF9OQU1FIjogIlpBUFAtV0VCIiwKICAgICJWSVRFX0FQUF9FTlYiOiAicHJvZHVjdGlvbiIsCiAgICAiVklURV9FTkFCTEVfQU5BTFlUSUNTIjogImZhbHNlIiwKICAgICJWSVRFX0VOQUJMRV9ERUJVRyI6ICJmYWxzZSIsCiAgICAiVklURV9FTkFCTEVfR0FNSUZJQ0FUSU9OIjogInRydWUiLAogICAgIlZJVEVfRU5BQkxFX0dNQUlMX0lOVEVHUkFUSU9OIjogImZhbHNlIgogIH0sCiAgInJld3JpdGVzIjogWwogICAgewogICAgICAic291cmNlIjogIi8oKD8hYXBpfF9uZXh0fGZhdmljb24uaWNvfGljb25zfHN3LmpzfHdvcmtib3h8bWFuaWZlc3Qud2VibWFuaWZlc3QpLiopIiwKICAgICAgImRlc3RpbmF0aW9uIjogIi9pbmRleC5odG1sIgogICAgfQogIF0sCiAgImhlYWRlcnMiOiBbCiAgICB7CiAgICAgICJzb3VyY2UiOiAiLyguKikiLAogICAgICAiaGVhZGVycyI6IFsKICAgICAgICB7CiAgICAgICAgICAia2V5IjogIlgtRnJhbWUtT3B0aW9ucyIsCiAgICAgICAgICAidmFsdWUiOiAiU0FNRU9SSUdJTiIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJrZXkiOiAiWC1Db250ZW50LVR5cGUtT3B0aW9ucyIsCiAgICAgICAgICAidmFsdWUiOiAibm9zbmlmZiIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJrZXkiOiAiWC1YU1MtUHJvdGVjdGlvbiIsCiAgICAgICAgICAidmFsdWUiOiAiMCIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJrZXkiOiAiU3RyaWN0LVRyYW5zcG9ydC1TZWN1cml0eSIsCiAgICAgICAgICAidmFsdWUiOiAibWF4LWFnZT02MzA3MjAwMDsgaW5jbHVkZVN1YkRvbWFpbnM7IHByZWxvYWQiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAia2V5IjogIlJlZmVycmVyLVBvbGljeSIsCiAgICAgICAgICAidmFsdWUiOiAic3RyaWN0LW9yaWdpbi13aGVuLWNyb3NzLW9yaWdpbiIKICAgICAgICB9LAogICAgICAgIHsKICAgICAgICAgICJrZXkiOiAiUGVybWlzc2lvbnMtUG9saWN5IiwKICAgICAgICAgICJ2YWx1ZSI6ICJjYW1lcmE9KCksIG1pY3JvcGhvbmU9KHNlbGYpLCBnZW9sb2NhdGlvbj0oc2VsZiksIHBheW1lbnQ9KCkiCiAgICAgICAgfSwKICAgICAgICB7CiAgICAgICAgICAia2V5IjogIkNvbnRlbnQtU2VjdXJpdHktUG9saWN5IiwKICAgICAgICAgICJ2YWx1ZSI6ICJkZWZhdWx0LXNyYyAnc2VsZic7IHNjcmlwdC1zcmMgJ3NlbGYnICd1bnNhZmUtaW5saW5lJzsgc3R5bGUtc3JjICdzZWxmJyAndW5zYWZlLWlubGluZScgaHR0cHM6Ly9mb250cy5nb29nbGVhcGlzLmNvbTsgaW1nLXNyYyAnc2VsZicgZGF0YTogYmxvYjogaHR0cHM6Ly9zdXBhYmFzZS5hdG9taWNhYnIuY29tLmJyIGh0dHBzOi8vemFwcC1tZWRpYS1wcm94eS5hZG0wMS53b3JrZXJzLmRldiBodHRwczovLyouZ29vZ2xldXNlcmNvbnRlbnQuY29tIGh0dHBzOi8vbGgzLmdvb2dsZXVzZXJjb250ZW50LmNvbSBodHRwczovL3Bwcy53aGF0c2FwcC5uZXQgaHR0cHM6Ly9tbWcud2hhdHNhcHAubmV0IGh0dHBzOi8vc3RhdGljLndoYXRzYXBwLm5ldDsgbWVkaWEtc3JjICdzZWxmJyBibG9iOiBodHRwczovL3N1cGFiYXNlLmF0b21pY2Fici5jb20uYnIgaHR0cHM6Ly96YXBwLW1lZGlhLXByb3h5LmFkbTAxLndvcmtlcnMuZGV2IGh0dHBzOi8vbW1nLndoYXRzYXBwLm5ldCBodHRwczovLyoud2hhdHNhcHAubmV0OyBmb250LXNyYyAnc2VsZicgZGF0YTogaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbTsgY29ubmVjdC1zcmMgJ3NlbGYnIGh0dHBzOi8vc3VwYWJhc2UuYXRvbWljYWJyLmNvbS5iciB3c3M6Ly9zdXBhYmFzZS5hdG9taWNhYnIuY29tLmJyIGh0dHBzOi8vZXZvbHV0aW9uLmF0b21pY2Fici5jb20uYnIgaHR0cHM6Ly9uOG4uYXRvbWljYWJyLmNvbS5iciBodHRwczovL3phcHAtbWVkaWEtcHJveHkuYWRtMDEud29ya2Vycy5kZXYgaHR0cHM6Ly8qLmluZ2VzdC5zZW50cnkuaW8gaHR0cHM6Ly8qLnNlbnRyeS5pbyBodHRwczovL2ZvbnRzLmdvb2dsZWFwaXMuY29tIGh0dHBzOi8vZm9udHMuZ3N0YXRpYy5jb207IHdvcmtlci1zcmMgJ3NlbGYnIGJsb2I6OyBmcmFtZS1hbmNlc3RvcnMgJ3NlbGYnOyBiYXNlLXVyaSAnc2VsZic7IGZvcm0tYWN0aW9uICdzZWxmJzsiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgewogICAgICAic291cmNlIjogIi9zdGF0aWMvKC4qKSIsCiAgICAgICJoZWFkZXJzIjogWwogICAgICAgIHsKICAgICAgICAgICJrZXkiOiAiQ2FjaGUtQ29udHJvbCIsCiAgICAgICAgICAidmFsdWUiOiAicHVibGljLCBtYXgtYWdlPTMxNTM2MDAwLCBpbW11dGFibGUiCiAgICAgICAgfQogICAgICBdCiAgICB9LAogICAgewogICAgICAic291cmNlIjogIi8oc3dcXC5qc3x3b3JrYm94LipcXC5qcykiLAogICAgICAiaGVhZGVycyI6IFsKICAgICAgICB7CiAgICAgICAgICAia2V5IjogIkNhY2hlLUNvbnRyb2wiLAogICAgICAgICAgInZhbHVlIjogInB1YmxpYywgbWF4LWFnZT0wLCBtdXN0LXJldmFsaWRhdGUiCiAgICAgICAgfQogICAgICBdCiAgICB9CiAgXQp9Cg==
{
"framework": "vite",
"buildCommand": "vite build",
"outputDirectory": "dist",
"installCommand": "bun install",
"rewrites": [
{
"source": "/((?!api|_next|favicon.ico|icons|sw.js|workbox|manifest.webmanifest).*)",
"destination": "/index.html"
}
],
"headers": [
{
"source": "/(.*)",
"headers": [
{
"key": "X-Frame-Options",
"value": "SAMEORIGIN"
},
{
"key": "X-Content-Type-Options",
"value": "nosniff"
},
{
"key": "X-XSS-Protection",
"value": "0"
},
{
"key": "Strict-Transport-Security",
"value": "max-age=63072000; includeSubDomains; preload"
},
{
"key": "Referrer-Policy",
"value": "strict-origin-when-cross-origin"
},
{
"key": "Permissions-Policy",
"value": "camera=(), microphone=(self), geolocation=(self), payment=()"
},
{
"key": "Content-Security-Policy",
"value": "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https://supabase.atomicabr.com.br https://zapp-media-proxy.adm01.workers.dev https://*.googleusercontent.com https://lh3.googleusercontent.com https://pps.whatsapp.net https://mmg.whatsapp.net https://static.whatsapp.net; media-src 'self' blob: https://supabase.atomicabr.com.br https://zapp-media-proxy.adm01.workers.dev https://mmg.whatsapp.net https://*.whatsapp.net; font-src 'self' data: https://fonts.gstatic.com; connect-src 'self' https://supabase.atomicabr.com.br wss://supabase.atomicabr.com.br https://evolution.atomicabr.com.br https://n8n.atomicabr.com.br https://zapp-media-proxy.adm01.workers.dev https://*.ingest.sentry.io https://*.sentry.io https://fonts.googleapis.com https://fonts.gstatic.com; worker-src 'self' blob:; frame-ancestors 'self'; base-uri 'self'; form-action 'self';"
}
]
},
{
"source": "/static/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
},
{
"source": "/(sw\\.js|workbox.*\\.js)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=0, must-revalidate"
}
]
}
]
}
Loading