diff --git a/pages/wallets/index.js b/pages/wallets/index.js index 78ac45a5..6acfd46e 100644 --- a/pages/wallets/index.js +++ b/pages/wallets/index.js @@ -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 ( -
- - loading wallets +
+ wallets unavailable + + this device does not support storage of cryptographic keys via IndexedDB +
) } - if (status === Status.PASSPHRASE_REQUIRED) { + if (keyError === KeyStatus.WRONG_KEY) { return (
@@ -55,33 +59,31 @@ export default function Wallet () { ) } - if (status === Status.WALLETS_UNAVAILABLE) { - return ( - -
- wallets unavailable - - this device does not support storage of cryptographic keys via IndexedDB - -
-
- ) - } - - if (status instanceof Error) { + if (walletsError) { return (
failed to load wallets - {status.message} + {walletsError.message}
) } - if (status === Status.NO_WALLETS && !showWallets) { + if (walletsLoading) { + return ( + +
+ + loading wallets +
+
+ ) + } + + if (wallets.length === 0 && !showWallets) { return (
diff --git a/wallets/client/context/hooks.js b/wallets/client/context/hooks.js index aab7cda1..c9abc6ed 100644 --- a/wallets/client/context/hooks.js +++ b/wallets/client/context/hooks.js @@ -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 { diff --git a/wallets/client/context/provider.js b/wallets/client/context/provider.js index 321e2e3d..3613bbdd 100644 --- a/wallets/client/context/provider.js +++ b/wallets/client/context/provider.js @@ -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 ( diff --git a/wallets/client/context/reducer.js b/wallets/client/context/reducer.js index 365c2475..27d2a1d5 100644 --- a/wallets/client/context/reducer.js +++ b/wallets/client/context/reducer.js @@ -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 - } -} diff --git a/wallets/client/hooks/indicator.js b/wallets/client/hooks/indicator.js index c9389679..53f4a832 100644 --- a/wallets/client/hooks/indicator.js +++ b/wallets/client/hooks/indicator.js @@ -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 } diff --git a/wallets/client/hooks/query.js b/wallets/client/hooks/query.js index 9d2328f4..e5b27cb2 100644 --- a/wallets/client/hooks/query.js +++ b/wallets/client/hooks/query.js @@ -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()