feat: Enhance Gemini analysis and image handling

Integrates Gemini 3.1 Pro for improved Forex chart analysis, incorporating detailed instructions on Smart Money Concepts, liquidity, and various confirmation indicators like Volume Delta, ATR, EMA, RSI, and VWAP.

Also includes image compression and cleanup utilities for testimonial uploads to manage storage efficiently. Firestore rules for signal data have been updated to accommodate longer strings for pair and timeframe.
This commit is contained in:
desartstudio95
2026-05-12 07:56:18 +02:00
parent 11981e28b0
commit a72d42c6d8
7 changed files with 268 additions and 16 deletions
+65
View File
@@ -0,0 +1,65 @@
import { storage } from './firebase';
import { listAll, deleteObject, ref } from 'firebase/storage';
export const compressImage = (file: File, maxWidth = 1200, quality = 0.7): Promise<File> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (event) => {
const img = new Image();
img.src = event.target?.result as string;
img.onload = () => {
const canvas = document.createElement('canvas');
let width = img.width;
let height = img.height;
if (width > maxWidth) {
height = Math.round((height * maxWidth) / width);
width = maxWidth;
}
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
if (!ctx) {
resolve(file); // falha segura
return;
}
ctx.drawImage(img, 0, 0, width, height);
canvas.toBlob((blob) => {
if (!blob) {
resolve(file);
return;
}
const compressedFile = new File([blob], file.name, {
type: 'image/jpeg',
lastModified: Date.now(),
});
resolve(compressedFile);
}, 'image/jpeg', quality);
};
img.onerror = (err) => resolve(file); // falha segura
};
reader.onerror = (err) => resolve(file); // falha segura
});
};
export const cleanupStorage = async (path: string, maxFiles: number = 100) => {
try {
const listRef = ref(storage, path);
const res = await listAll(listRef);
if (res.items.length > maxFiles) {
// Sort by name (which starts with Date.now()_filename, so alphabetical sort works as chronological sort)
const items = res.items.sort((a, b) => a.name.localeCompare(b.name));
// Delete older items (from beginning of sorted array)
const itemsToDelete = items.slice(0, items.length - maxFiles);
const deletePromises = itemsToDelete.map((itemRef) => deleteObject(itemRef));
await Promise.all(deletePromises);
console.log(`Cleaned up ${itemsToDelete.length} files from ${path}`);
}
} catch (error) {
console.warn("Cleanup storage error:", error);
}
};