diff --git a/components/use-indexeddb.js b/components/use-indexeddb.js index 1733970e..d4f651b3 100644 --- a/components/use-indexeddb.js +++ b/components/use-indexeddb.js @@ -3,6 +3,7 @@ import { useState, useEffect, useCallback, useRef } from 'react' function useIndexedDB (dbName, storeName, version = 1, indices = []) { const [db, setDb] = useState(null) const [error, setError] = useState(null) + const [notSupported, setNotSupported] = useState(false) const operationQueue = useRef([]) const handleError = useCallback((error) => { @@ -27,36 +28,47 @@ function useIndexedDB (dbName, storeName, version = 1, indices = []) { useEffect(() => { let isMounted = true - const request = window.indexedDB.open(dbName, version) + let request + try { + if (!window.indexedDB) { + console.log('IndexedDB is not supported') + setNotSupported(true) + return + } - request.onerror = (event) => { - handleError(new Error('Error opening database')) - } + request = window.indexedDB.open(dbName, version) - request.onsuccess = (event) => { - if (isMounted) { - const database = event.target.result - database.onversionchange = () => { - database.close() - setDb(null) - handleError(new Error('Database is outdated, please reload the page')) + request.onerror = (event) => { + handleError(new Error('Error opening database')) + } + + request.onsuccess = (event) => { + if (isMounted) { + const database = event.target.result + database.onversionchange = () => { + database.close() + setDb(null) + handleError(new Error('Database is outdated, please reload the page')) + } + setDb(database) + processQueue(database) } - setDb(database) - processQueue(database) } - } - request.onupgradeneeded = (event) => { - const database = event.target.result - try { - const store = database.createObjectStore(storeName, { keyPath: 'id', autoIncrement: true }) + request.onupgradeneeded = (event) => { + const database = event.target.result + try { + const store = database.createObjectStore(storeName, { keyPath: 'id', autoIncrement: true }) - indices.forEach(index => { - store.createIndex(index.name, index.keyPath, index.options) - }) - } catch (error) { - handleError(new Error('Error upgrading database: ' + error.message)) + indices.forEach(index => { + store.createIndex(index.name, index.keyPath, index.options) + }) + } catch (error) { + handleError(new Error('Error upgrading database: ' + error.message)) + } } + } catch (error) { + handleError(new Error('Error opening database: ' + error.message)) } return () => { @@ -68,6 +80,13 @@ function useIndexedDB (dbName, storeName, version = 1, indices = []) { }, [dbName, storeName, version, indices, handleError, processQueue]) const queueOperation = useCallback((operation) => { + if (notSupported) { + return Promise.reject(new Error('IndexedDB is not supported')) + } + if (error) { + return Promise.reject(new Error('Database error: ' + error.message)) + } + return new Promise((resolve, reject) => { const wrappedOperation = (db) => { try { @@ -81,7 +100,7 @@ function useIndexedDB (dbName, storeName, version = 1, indices = []) { operationQueue.current.push(wrappedOperation) processQueue(db) }) - }, [processQueue, db]) + }, [processQueue, db, notSupported, error]) const add = useCallback((value) => { return queueOperation((db) => { @@ -267,7 +286,7 @@ function useIndexedDB (dbName, storeName, version = 1, indices = []) { }) }, [queueOperation, storeName]) - return { add, get, getAll, update, remove, clear, getByIndex, getAllByIndex, getPage, error } + return { add, get, getAll, update, remove, clear, getByIndex, getAllByIndex, getPage, error, notSupported } } export default useIndexedDB diff --git a/components/wallet-logger.js b/components/wallet-logger.js index 569445b0..94eda656 100644 --- a/components/wallet-logger.js +++ b/components/wallet-logger.js @@ -15,7 +15,7 @@ export function WalletLogs ({ wallet, embedded }) { const { logs, setLogs, hasMore, loadMore, loadLogs, loading } = useWalletLogs(wallet) useEffect(() => { loadLogs() - }, [wallet]) + }, [loadLogs]) const showModal = useShowModal() @@ -93,22 +93,26 @@ function useWalletLogDB () { const { me } = useMe() const dbName = `app:storage${me ? `:${me.id}` : ''}` const idbStoreName = 'wallet_logs' - const { add, getPage, clear, error: idbError } = useIndexedDB(dbName, idbStoreName, 1, INDICES) - return { add, getPage, clear, error: idbError } + const { add, getPage, clear, error, notSupported } = useIndexedDB(dbName, idbStoreName, 1, INDICES) + return { add, getPage, clear, error, notSupported } } export function useWalletLogger (wallet, setLogs) { - const { add, clear } = useWalletLogDB() + const { add, clear, notSupported } = useWalletLogDB() const appendLog = useCallback(async (wallet, level, message) => { const log = { wallet: tag(wallet), level, message, ts: +new Date() } try { - await add(log) + if (notSupported) { + console.log('cannot persist wallet log: indexeddb not supported') + } else { + await add(log) + } setLogs?.(prevLogs => [log, ...prevLogs]) } catch (error) { - console.error('Failed to append log:', error) + console.error('Failed to append wallet log:', error) } - }, [add]) + }, [add, notSupported]) const [deleteServerWalletLogs] = useMutation( gql` @@ -130,13 +134,17 @@ export function useWalletLogger (wallet, setLogs) { if (!wallet || wallet.sendPayment) { try { const walletTag = wallet ? tag(wallet) : null - await clear('wallet_ts', walletTag ? window.IDBKeyRange.bound([walletTag, 0], [walletTag, Infinity]) : null) + if (notSupported) { + console.log('cannot clear wallet logs: indexeddb not supported') + } else { + await clear('wallet_ts', walletTag ? window.IDBKeyRange.bound([walletTag, 0], [walletTag, Infinity]) : null) + } setLogs?.(logs => logs.filter(l => wallet ? l.wallet !== tag(wallet) : false)) } catch (e) { console.error('failed to delete logs', e) } } - }, [clear, deleteServerWalletLogs, setLogs]) + }, [clear, deleteServerWalletLogs, setLogs, notSupported]) const log = useCallback(level => message => { if (!wallet) { @@ -169,20 +177,24 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) { const [cursor, setCursor] = useState(null) const [loading, setLoading] = useState(true) - const { getPage, error: idbError } = useWalletLogDB() + const { getPage, error, notSupported } = useWalletLogDB() const [getWalletLogs] = useLazyQuery(WALLET_LOGS, SSR ? {} : { fetchPolicy: 'cache-and-network' }) const loadLogsPage = useCallback(async (page, pageSize, wallet) => { try { let result = { data: [], hasMore: false } - const indexName = wallet ? 'wallet_ts' : 'ts' - const query = wallet ? window.IDBKeyRange.bound([tag(wallet), -Infinity], [tag(wallet), Infinity]) : null - result = await getPage(page, pageSize, indexName, query, 'prev') - // no walletType means we're using the local IDB - if (wallet && !wallet.walletType) { - return result - } + if (notSupported) { + console.log('cannot get client wallet logs: indexeddb not supported') + } else { + const indexName = wallet ? 'wallet_ts' : 'ts' + const query = wallet ? window.IDBKeyRange.bound([tag(wallet), -Infinity], [tag(wallet), Infinity]) : null + result = await getPage(page, pageSize, indexName, query, 'prev') + // no walletType means we're using the local IDB + if (wallet && !wallet.walletType) { + return result + } + } const { data } = await getWalletLogs({ variables: { type: wallet?.walletType, @@ -207,10 +219,10 @@ export function useWalletLogs (wallet, initialPage = 1, logsPerPage = 10) { console.error('Error loading logs from IndexedDB:', error) return { data: [], total: 0, hasMore: false } } - }, [getPage, setCursor, cursor]) + }, [getPage, setCursor, cursor, notSupported]) - if (idbError) { - console.error('IndexedDB error:', idbError) + if (error) { + console.error('IndexedDB error:', error) } const loadMore = useCallback(async () => {