catch when indexeddb is not available fix #1462

This commit is contained in:
k00b 2024-10-07 10:51:25 -05:00
parent 154c0e0a4a
commit 070b350211
2 changed files with 76 additions and 45 deletions

View File

@ -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

View File

@ -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 () => {