mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
190 lines
4.8 KiB
TypeScript
190 lines
4.8 KiB
TypeScript
import { useCallback, useEffect, useState } from 'react'
|
|
|
|
/**
|
|
* Email message for IndexedDB storage
|
|
*/
|
|
export interface StoredMessage {
|
|
id: string
|
|
messageId: string
|
|
from: string
|
|
to: string[]
|
|
subject: string
|
|
body: string
|
|
receivedAt: number
|
|
isRead: boolean
|
|
isStarred: boolean
|
|
folderName: string
|
|
createdAt: number
|
|
}
|
|
|
|
/**
|
|
* Hook for IndexedDB wrapper for offline email storage
|
|
* Manages local caching of email messages
|
|
*/
|
|
export interface UseEmailStoreResult {
|
|
/** Retrieve all stored messages */
|
|
getMessages: (folderName?: string) => Promise<StoredMessage[]>
|
|
/** Save messages to offline storage */
|
|
saveMessages: (messages: StoredMessage[]) => Promise<void>
|
|
/** Clear all stored messages */
|
|
clear: () => Promise<void>
|
|
/** Whether storage is initialized */
|
|
isReady: boolean
|
|
/** Error if initialization failed */
|
|
error: Error | null
|
|
}
|
|
|
|
const DB_NAME = 'metabuilder_email'
|
|
const STORE_NAME = 'messages'
|
|
const DB_VERSION = 1
|
|
|
|
/**
|
|
* IndexedDB wrapper for offline email storage
|
|
* @returns Email store interface
|
|
*/
|
|
export function useEmailStore(): UseEmailStoreResult {
|
|
const [isReady, setIsReady] = useState(false)
|
|
const [error, setError] = useState<Error | null>(null)
|
|
const [db, setDb] = useState<IDBDatabase | null>(null)
|
|
|
|
/**
|
|
* Initialize IndexedDB connection
|
|
*/
|
|
useEffect(() => {
|
|
const initDB = async () => {
|
|
try {
|
|
const request = indexedDB.open(DB_NAME, DB_VERSION)
|
|
|
|
request.onerror = () => {
|
|
const err = new Error('Failed to open IndexedDB')
|
|
setError(err)
|
|
console.error(err)
|
|
}
|
|
|
|
request.onsuccess = () => {
|
|
const database = request.result
|
|
|
|
// Create object store if needed
|
|
if (database.objectStoreNames.length === 0) {
|
|
database.close()
|
|
const createRequest = indexedDB.open(DB_NAME, DB_VERSION + 1)
|
|
createRequest.onupgradeneeded = (event: IDBVersionChangeEvent) => {
|
|
const db = (event.target as IDBOpenDBRequest).result
|
|
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
db.createObjectStore(STORE_NAME, { keyPath: 'id' })
|
|
}
|
|
}
|
|
createRequest.onsuccess = () => {
|
|
setDb(createRequest.result)
|
|
setIsReady(true)
|
|
}
|
|
} else {
|
|
setDb(database)
|
|
setIsReady(true)
|
|
}
|
|
}
|
|
|
|
request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
|
|
const database = (event.target as IDBOpenDBRequest).result
|
|
if (!database.objectStoreNames.contains(STORE_NAME)) {
|
|
database.createObjectStore(STORE_NAME, { keyPath: 'id' })
|
|
}
|
|
}
|
|
} catch (err) {
|
|
const initError = err instanceof Error ? err : new Error('Failed to initialize storage')
|
|
setError(initError)
|
|
}
|
|
}
|
|
|
|
initDB()
|
|
|
|
return () => {
|
|
db?.close()
|
|
}
|
|
}, [])
|
|
|
|
/**
|
|
* Retrieve messages from storage
|
|
*/
|
|
const getMessages = useCallback(
|
|
async (folderName?: string): Promise<StoredMessage[]> => {
|
|
if (!db) return []
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(STORE_NAME, 'readonly')
|
|
const store = transaction.objectStore(STORE_NAME)
|
|
const request = store.getAll()
|
|
|
|
request.onsuccess = () => {
|
|
const messages = request.result as StoredMessage[]
|
|
const filtered = folderName
|
|
? messages.filter(m => m.folderName === folderName)
|
|
: messages
|
|
resolve(filtered)
|
|
}
|
|
|
|
request.onerror = () => {
|
|
reject(new Error('Failed to retrieve messages'))
|
|
}
|
|
})
|
|
},
|
|
[db]
|
|
)
|
|
|
|
/**
|
|
* Save messages to storage
|
|
*/
|
|
const saveMessages = useCallback(
|
|
async (messages: StoredMessage[]): Promise<void> => {
|
|
if (!db) return
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(STORE_NAME, 'readwrite')
|
|
const store = transaction.objectStore(STORE_NAME)
|
|
|
|
messages.forEach(message => {
|
|
store.put({ ...message, createdAt: Date.now() })
|
|
})
|
|
|
|
transaction.oncomplete = () => {
|
|
resolve()
|
|
}
|
|
|
|
transaction.onerror = () => {
|
|
reject(new Error('Failed to save messages'))
|
|
}
|
|
})
|
|
},
|
|
[db]
|
|
)
|
|
|
|
/**
|
|
* Clear all stored messages
|
|
*/
|
|
const clear = useCallback(async (): Promise<void> => {
|
|
if (!db) return
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = db.transaction(STORE_NAME, 'readwrite')
|
|
const store = transaction.objectStore(STORE_NAME)
|
|
const request = store.clear()
|
|
|
|
request.onsuccess = () => {
|
|
resolve()
|
|
}
|
|
|
|
request.onerror = () => {
|
|
reject(new Error('Failed to clear storage'))
|
|
}
|
|
})
|
|
}, [db])
|
|
|
|
return {
|
|
getMessages,
|
|
saveMessages,
|
|
clear,
|
|
isReady,
|
|
error,
|
|
}
|
|
}
|