From bd0515c31b0fd2344072427d1e5082651473f4f1 Mon Sep 17 00:00:00 2001 From: pas1ko Date: Sat, 13 Aug 2022 18:31:20 +0100 Subject: [PATCH] Implement token search persist for popup ext --- src/app/components/blocks/OverviewContent.tsx | 4 +- src/app/components/screens/Popup.tsx | 5 +- src/app/hooks/tokenList.tsx | 74 ++++++++++++++++++- 3 files changed, 78 insertions(+), 5 deletions(-) diff --git a/src/app/components/blocks/OverviewContent.tsx b/src/app/components/blocks/OverviewContent.tsx index 0a9011164..865046c17 100644 --- a/src/app/components/blocks/OverviewContent.tsx +++ b/src/app/components/blocks/OverviewContent.tsx @@ -134,7 +134,9 @@ const TokenList = memo<{ tokenType: TokenType }>(({ tokenType }) => { searchInputRef, tokenIdSearchInputRef, loadMoreTriggerRef, - } = useTokenList(tokenType, handleAccountTokensReset); + } = useTokenList(tokenType, { + onAccountTokensReset: handleAccountTokensReset, + }); // A little hack to avoid using `manageModeEnabled` dependency const manageModeEnabledRef = useRef(); diff --git a/src/app/components/screens/Popup.tsx b/src/app/components/screens/Popup.tsx index 98e75b8eb..704abf481 100644 --- a/src/app/components/screens/Popup.tsx +++ b/src/app/components/screens/Popup.tsx @@ -170,7 +170,10 @@ const TokenList: FC<{ tokenType: TokenType }> = ({ tokenType }) => { searchInputRef, tokenIdSearchInputRef, loadMoreTriggerRef, - } = useTokenList(tokenType, handleAccountTokensReset); + } = useTokenList(tokenType, { + onAccountTokensReset: handleAccountTokensReset, + searchPersist: tokenType === TokenType.NFT, + }); const controlBar = useMemo( () => ( diff --git a/src/app/hooks/tokenList.tsx b/src/app/hooks/tokenList.tsx index 92bf63dca..1098cca3b 100644 --- a/src/app/hooks/tokenList.tsx +++ b/src/app/hooks/tokenList.tsx @@ -1,6 +1,14 @@ -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + Dispatch, + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; import { useAtomValue } from "jotai"; import { ethers } from "ethers"; +import { storage } from "lib/ext/storage"; import { TokenStandard, TokenType } from "core/types"; import { createTokenSlug, detectNFTStandard } from "core/common/tokens"; @@ -16,7 +24,10 @@ import { export function useTokenList( tokenType: TokenType, - onAccountTokensReset?: () => void + opts: { + onAccountTokensReset?: () => void; + searchPersist?: boolean; + } = {} ) { const currentAccount = useAtomValue(currentAccountAtom); const chainId = useChainId(); @@ -30,6 +41,12 @@ export function useTokenList( ); const [manageModeEnabled, setManageModeEnabled] = useState(false); + useTokenSearchPersist( + opts.searchPersist ?? false, + searchValue, + setSearchValue + ); + const combinedSearchValue = useMemo(() => { if (!searchValue) return undefined; if (!tokenIdSearchValue) return searchValue; @@ -44,7 +61,7 @@ export function useTokenList( withDisabled: manageModeEnabled || Boolean(isNftsSelected && combinedSearchValue), search: combinedSearchValue, - onReset: onAccountTokensReset, + onReset: opts.onAccountTokensReset, } ); @@ -174,3 +191,54 @@ export function useTokenList( loadMoreTriggerRef, }; } + +const TOKEN_SEARCH_PERSIST = "token_search_persist"; +type TokenSearchPersist = { + value: string; + addedAt: number; +}; + +function useTokenSearchPersist( + enabled: boolean, + searchValue: string | null, + setSearchValue: Dispatch> +) { + useEffect(() => { + if (!enabled) return; + + (async () => { + try { + const persist = await storage.fetchForce( + TOKEN_SEARCH_PERSIST + ); + if (!persist) return; + + const { value, addedAt } = persist; + if (ethers.utils.isAddress(value) && addedAt > Date.now() - 30_000) { + setSearchValue(value); + } else { + await storage.remove(TOKEN_SEARCH_PERSIST); + } + } catch (err) { + console.error(err); + } + })(); + }, [enabled, setSearchValue]); + + useEffect(() => { + if (!enabled) return; + + (async () => { + try { + if (!searchValue || !ethers.utils.isAddress(searchValue)) return; + + await storage.put(TOKEN_SEARCH_PERSIST, { + value: searchValue, + addedAt: Date.now(), + }); + } catch (err) { + console.error(err); + } + })(); + }, [enabled, searchValue]); +}