// static/js/db.js const DB_NAME = 'AlphaChatFileStore'; const STORE_NAME = 'files'; // *** قدم 1: نسخه دیتابیس را افزایش می‌دهیم تا فرآیند ارتقا فعال شود *** const DB_VERSION = 2; let db; // 1. مقداردهی اولیه و باز کردن دیتابیس export function initDB() { return new Promise((resolve, reject) => { console.log(`در حال تلاش برای باز کردن دیتابیس ${DB_NAME} با نسخه ${DB_VERSION}...`); const request = indexedDB.open(DB_NAME, DB_VERSION); request.onerror = (event) => { console.error("خطای حیاتی در باز کردن IndexedDB:", event.target.error); reject("خطای دیتابیس. لطفا از فعال بودن کوکی‌ها و فضای ذخیره‌سازی مرورگر اطمینان حاصل کنید."); }; request.onsuccess = (event) => { db = event.target.result; console.log("IndexedDB با موفقیت باز و آماده استفاده است."); resolve(db); }; // این تابع فقط زمانی اجرا می‌شود که دیتابیس برای اولین بار ساخته شود یا نسخه آن (DB_VERSION) افزایش یابد. request.onupgradeneeded = (event) => { console.log("رویداد onupgradeneeded فعال شد. در حال ارتقا ساختار دیتابیس..."); const db = event.target.result; // *** قدم 2: منطق ارتقا را هوشمند می‌کنیم *** // ابتدا بررسی می‌کنیم که آیا ساختار قدیمی (و اشتباه) وجود دارد یا نه if (db.objectStoreNames.contains(STORE_NAME)) { // اگر وجود داشت، آن را حذف می‌کنیم تا راه برای ساختار جدید باز شود. db.deleteObjectStore(STORE_NAME); console.log("Object store قدیمی 'files' پیدا و برای ارتقا حذف شد."); } // حالا ساختار جدید و صحیح را ایجاد می‌کنیم. // با حذف keyPath، به IndexedDB اجازه می‌دهیم کلید را به صورت خودکار و خارج از آبجکت مدیریت کند. // این کار مشکل اصلی شما را به طور قطعی حل می‌کند. const store = db.createObjectStore(STORE_NAME, { autoIncrement: true }); // یک ایندکس برای جستجوی فایل‌ها بر اساس زمان ایجاد می‌کنیم. store.createIndex('timestamp', 'timestamp', { unique: false }); console.log("Object store جدید و صحیح 'files' با موفقیت ساخته شد."); }; }); } // 2. ذخیره کردن یک فایل در دیتابیس export function storeFile(file) { return new Promise((resolve, reject) => { if (!db) { // این حالت نباید رخ دهد چون main.js منتظر اتمام initDB می‌ماند. reject("دیتابیس هنوز مقداردهی اولیه نشده است."); return; } const transaction = db.transaction([STORE_NAME], 'readwrite'); const store = transaction.objectStore(STORE_NAME); const fileRecord = { file: file, name: file.name, type: file.type, timestamp: Date.now() }; const request = store.add(fileRecord); request.onsuccess = (event) => { // event.target.result حاوی کلید (ID) اختصاص داده شده به رکورد جدید است. resolve(event.target.result); }; request.onerror = (event) => { console.error("خطا در ذخیره فایل در IndexedDB:", event.target.error); reject("ذخیره فایل در دیتابیس محلی ناموفق بود."); }; }); } // 3. بازیابی یک فایل از دیتابیس با استفاده از ID export function getFile(id) { return new Promise((resolve, reject) => { if (!db) { reject("دیتابیس مقداردهی اولیه نشده است."); return; } // کلیدهای تولید شده توسط autoIncrement همیشه عددی هستند. // این تبدیل، اطمینان می‌دهد که حتی اگر ID به صورت رشته ذخیره شده باشد، به درستی بازیابی شود. const numericId = typeof id === 'string' ? parseInt(id, 10) : id; if (isNaN(numericId)) { reject("ID فایل برای بازیابی نامعتبر است."); return; } const transaction = db.transaction([STORE_NAME], 'readonly'); const store = transaction.objectStore(STORE_NAME); const request = store.get(numericId); request.onsuccess = (event) => { if (event.target.result) { // خود فایل که یک Blob است را باز می‌گردانیم. resolve(event.target.result.file); } else { reject("فایلی با این ID در دیتابیس محلی یافت نشد."); } }; request.onerror = (event) => { console.error("خطا در بازیابی فایل:", event.target.error); reject("بازیابی فایل ناموفق بود."); }; }); } // 4. پاک کردن فایل‌های قدیمی‌تر از یک هفته export function cleanupOldFiles() { return new Promise((resolve, reject) => { if (!db) { reject("دیتابیس مقداردهی اولیه نشده است."); return; } const transaction = db.transaction([STORE_NAME], 'readwrite'); const store = transaction.objectStore(STORE_NAME); const index = store.index('timestamp'); const oneWeekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000); const range = IDBKeyRange.upperBound(oneWeekAgo); const request = index.openCursor(range); let deletedCount = 0; request.onsuccess = (event) => { const cursor = event.target.result; if (cursor) { cursor.delete(); deletedCount++; cursor.continue(); } else { if(deletedCount > 0) console.log(`${deletedCount} فایل قدیمی و منقضی شده از IndexedDB پاک شد.`); resolve(); } }; request.onerror = (event) => { console.error("خطا در پاکسازی فایل‌های قدیمی:", event.target.error); reject("پاکسازی فایل‌های قدیمی ناموفق بود."); }; }); }