Fix wallets error handling order (#2286)
This commit is contained in:
parent
2ee685d5a9
commit
5502d29d7e
@ -1,6 +1,6 @@
|
||||
import { getGetServerSideProps } from '@/api/ssrApollo'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { useWallets, useTemplates, DndProvider, Status, useStatus } from '@/wallets/client/context'
|
||||
import { useWallets, useTemplates, DndProvider, KeyStatus, useWalletsLoading, useKeyError, useWalletsError } from '@/wallets/client/context'
|
||||
import { WalletCard, WalletLayout, WalletLayoutHeader, WalletLayoutLink, WalletLayoutSubHeader } from '@/wallets/client/components'
|
||||
import styles from '@/styles/wallet.module.css'
|
||||
import { usePassphrasePrompt, useShowPassphrase, useSetWalletPriorities } from '@/wallets/client/hooks'
|
||||
@ -13,7 +13,9 @@ export const getServerSideProps = getGetServerSideProps({ authRequired: true })
|
||||
|
||||
export default function Wallet () {
|
||||
const wallets = useWallets()
|
||||
const status = useStatus()
|
||||
const walletsLoading = useWalletsLoading()
|
||||
const walletsError = useWalletsError()
|
||||
const keyError = useKeyError()
|
||||
const [showWallets, setShowWallets] = useState(false)
|
||||
const templates = useTemplates()
|
||||
const showPassphrase = useShowPassphrase()
|
||||
@ -29,18 +31,20 @@ export default function Wallet () {
|
||||
}
|
||||
}, [wallets, templates, searchFilter])
|
||||
|
||||
if (status === Status.LOADING_WALLETS) {
|
||||
if (keyError === KeyStatus.KEY_STORAGE_UNAVAILABLE) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1 text-muted'>
|
||||
<Moon className='spin fill-grey' height={28} width={28} />
|
||||
<small className='d-block mt-3 text-muted'>loading wallets</small>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1'>
|
||||
<span className='text-muted fw-bold my-1'>wallets unavailable</span>
|
||||
<small className='d-block text-muted'>
|
||||
this device does not support storage of cryptographic keys via IndexedDB
|
||||
</small>
|
||||
</div>
|
||||
</WalletLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (status === Status.PASSPHRASE_REQUIRED) {
|
||||
if (keyError === KeyStatus.WRONG_KEY) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1'>
|
||||
@ -55,33 +59,31 @@ export default function Wallet () {
|
||||
)
|
||||
}
|
||||
|
||||
if (status === Status.WALLETS_UNAVAILABLE) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1'>
|
||||
<span className='text-muted fw-bold my-1'>wallets unavailable</span>
|
||||
<small className='d-block text-muted'>
|
||||
this device does not support storage of cryptographic keys via IndexedDB
|
||||
</small>
|
||||
</div>
|
||||
</WalletLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (status instanceof Error) {
|
||||
if (walletsError) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1'>
|
||||
<span className='text-muted fw-bold my-1'>failed to load wallets</span>
|
||||
<small className='d-block text-muted'>
|
||||
{status.message}
|
||||
{walletsError.message}
|
||||
</small>
|
||||
</div>
|
||||
</WalletLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (status === Status.NO_WALLETS && !showWallets) {
|
||||
if (walletsLoading) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1 text-muted'>
|
||||
<Moon className='spin fill-grey' height={28} width={28} />
|
||||
<small className='d-block mt-3 text-muted'>loading wallets</small>
|
||||
</div>
|
||||
</WalletLayout>
|
||||
)
|
||||
}
|
||||
|
||||
if (wallets.length === 0 && !showWallets) {
|
||||
return (
|
||||
<WalletLayout>
|
||||
<div className='py-5 text-center d-flex flex-column align-items-center justify-content-center flex-grow-1'>
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
useWalletMigrationMutation, CryptoKeyRequiredError, useIsWrongKey
|
||||
} from '@/wallets/client/hooks'
|
||||
import { WalletConfigurationError } from '@/wallets/client/errors'
|
||||
import { SET_WALLETS, WRONG_KEY, KEY_MATCH, NO_KEY, useWalletsDispatch, WALLETS_QUERY_ERROR } from '@/wallets/client/context'
|
||||
import { SET_WALLETS, WRONG_KEY, KEY_MATCH, useWalletsDispatch, WALLETS_QUERY_ERROR, KEY_STORAGE_UNAVAILABLE } from '@/wallets/client/context'
|
||||
import { useIndexedDB } from '@/components/use-indexeddb'
|
||||
|
||||
export function useServerWallets () {
|
||||
@ -110,7 +110,7 @@ export function useKeyInit () {
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window.indexedDB === 'undefined') {
|
||||
dispatch({ type: NO_KEY })
|
||||
dispatch({ type: KEY_STORAGE_UNAVAILABLE })
|
||||
} else if (wrongKey) {
|
||||
dispatch({ type: WRONG_KEY })
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { createContext, useContext, useReducer } from 'react'
|
||||
import walletsReducer, { Status } from './reducer'
|
||||
import walletsReducer from './reducer'
|
||||
import { useServerWallets, useKeyCheck, useAutomatedRetries, useKeyInit, useWalletMigration } from './hooks'
|
||||
import { WebLnProvider } from '@/wallets/lib/protocols/webln'
|
||||
|
||||
@ -17,14 +17,14 @@ export function useTemplates () {
|
||||
return templates
|
||||
}
|
||||
|
||||
export function useLoading () {
|
||||
const { status } = useContext(WalletsContext)
|
||||
return status === Status.LOADING_WALLETS
|
||||
export function useWalletsLoading () {
|
||||
const { walletsLoading } = useContext(WalletsContext)
|
||||
return walletsLoading
|
||||
}
|
||||
|
||||
export function useStatus () {
|
||||
const { status } = useContext(WalletsContext)
|
||||
return status
|
||||
export function useWalletsError () {
|
||||
const { walletsError } = useContext(WalletsContext)
|
||||
return walletsError
|
||||
}
|
||||
|
||||
export function useWalletsDispatch () {
|
||||
@ -41,13 +41,20 @@ export function useKeyHash () {
|
||||
return keyHash
|
||||
}
|
||||
|
||||
export function useKeyError () {
|
||||
const { keyError } = useContext(WalletsContext)
|
||||
return keyError
|
||||
}
|
||||
|
||||
export default function WalletsProvider ({ children }) {
|
||||
const [state, dispatch] = useReducer(walletsReducer, {
|
||||
status: Status.LOADING_WALLETS,
|
||||
wallets: [],
|
||||
walletsLoading: true,
|
||||
walletsError: null,
|
||||
templates: [],
|
||||
key: null,
|
||||
keyHash: null
|
||||
keyHash: null,
|
||||
keyError: null
|
||||
})
|
||||
|
||||
return (
|
||||
|
@ -1,12 +1,9 @@
|
||||
import { isTemplate, isWallet } from '@/wallets/lib/util'
|
||||
|
||||
// states that dictate if we show a button or wallets on the wallets page
|
||||
export const Status = {
|
||||
LOADING_WALLETS: 'LOADING_WALLETS',
|
||||
NO_WALLETS: 'NO_WALLETS',
|
||||
HAS_WALLETS: 'HAS_WALLETS',
|
||||
PASSPHRASE_REQUIRED: 'PASSPHRASE_REQUIRED',
|
||||
WALLETS_UNAVAILABLE: 'WALLETS_UNAVAILABLE'
|
||||
export const KeyStatus = {
|
||||
KEY_MATCH: 'KEY_MATCH',
|
||||
NO_KEY: 'NO_KEY',
|
||||
WRONG_KEY: 'WRONG_KEY'
|
||||
}
|
||||
|
||||
// wallet actions
|
||||
@ -14,7 +11,7 @@ export const SET_WALLETS = 'SET_WALLETS'
|
||||
export const SET_KEY = 'SET_KEY'
|
||||
export const WRONG_KEY = 'WRONG_KEY'
|
||||
export const KEY_MATCH = 'KEY_MATCH'
|
||||
export const NO_KEY = 'KEY_UNAVAILABLE'
|
||||
export const KEY_STORAGE_UNAVAILABLE = 'KEY_STORAGE_UNAVAILABLE'
|
||||
export const WALLETS_QUERY_ERROR = 'WALLETS_QUERY_ERROR'
|
||||
|
||||
export default function reducer (state, action) {
|
||||
@ -28,7 +25,8 @@ export default function reducer (state, action) {
|
||||
.sort((a, b) => a.name.localeCompare(b.name))
|
||||
return {
|
||||
...state,
|
||||
status: transitionStatus(action, state, wallets.length > 0 ? Status.HAS_WALLETS : Status.NO_WALLETS),
|
||||
walletsLoading: false,
|
||||
walletsError: null,
|
||||
wallets,
|
||||
templates
|
||||
}
|
||||
@ -36,7 +34,8 @@ export default function reducer (state, action) {
|
||||
case WALLETS_QUERY_ERROR:
|
||||
return {
|
||||
...state,
|
||||
status: transitionStatus(action, state, action.error)
|
||||
walletsLoading: false,
|
||||
walletsError: action.error
|
||||
}
|
||||
case SET_KEY:
|
||||
return {
|
||||
@ -47,32 +46,19 @@ export default function reducer (state, action) {
|
||||
case WRONG_KEY:
|
||||
return {
|
||||
...state,
|
||||
status: transitionStatus(action, state, Status.PASSPHRASE_REQUIRED)
|
||||
keyError: KeyStatus.WRONG_KEY
|
||||
}
|
||||
case KEY_MATCH:
|
||||
return {
|
||||
...state,
|
||||
status: transitionStatus(action, state, state.wallets.length > 0 ? Status.HAS_WALLETS : Status.NO_WALLETS)
|
||||
keyError: null
|
||||
}
|
||||
case NO_KEY:
|
||||
case KEY_STORAGE_UNAVAILABLE:
|
||||
return {
|
||||
...state,
|
||||
status: transitionStatus(action, state, Status.WALLETS_UNAVAILABLE)
|
||||
keyError: KeyStatus.KEY_STORAGE_UNAVAILABLE
|
||||
}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
function transitionStatus ({ type }, { status: from }, to) {
|
||||
switch (type) {
|
||||
case SET_WALLETS: {
|
||||
return (from instanceof Error || [Status.PASSPHRASE_REQUIRED, Status.WALLETS_UNAVAILABLE].includes(from)) ? from : to
|
||||
}
|
||||
case KEY_MATCH: {
|
||||
return (from instanceof Error || from === Status.LOADING_WALLETS) ? from : to
|
||||
}
|
||||
default:
|
||||
return to
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useWallets, useLoading } from '@/wallets/client/context'
|
||||
import { useWallets, useWalletsLoading } from '@/wallets/client/context'
|
||||
|
||||
export function useWalletIndicator () {
|
||||
const wallets = useWallets()
|
||||
const loading = useLoading()
|
||||
const loading = useWalletsLoading()
|
||||
return !loading && wallets.length === 0
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import { timeoutSignal } from '@/lib/time'
|
||||
import { WALLET_SEND_PAYMENT_TIMEOUT_MS } from '@/lib/constants'
|
||||
import { useToast } from '@/components/toast'
|
||||
import { useMe } from '@/components/me'
|
||||
import { useWallets, useLoading as useWalletsLoading } from '@/wallets/client/context'
|
||||
import { useWallets, useWalletsLoading } from '@/wallets/client/context'
|
||||
|
||||
export function useWalletsQuery () {
|
||||
const { me } = useMe()
|
||||
|
Loading…
x
Reference in New Issue
Block a user