diff --git a/packages/nextjs/components/NetworksDropdown.tsx b/packages/nextjs/components/NetworksDropdown.tsx index 260fcdf6..5f5c177c 100644 --- a/packages/nextjs/components/NetworksDropdown.tsx +++ b/packages/nextjs/components/NetworksDropdown.tsx @@ -10,7 +10,7 @@ import { getPopularTargetNetworks } from "~~/utils/scaffold-eth"; type Options = { value: number | string; label: string; - icon?: string | ReactNode; + icon: string | ReactNode; isTestnet?: boolean; }; @@ -36,7 +36,7 @@ const getIconComponent = (iconName: string | undefined) => { }; const networks = getPopularTargetNetworks(); -const groupedOptions = networks.reduce( +const initialGroupedOptions = networks.reduce( (groups, network) => { if (network.id === 31337) { groups.localhost.options.push({ @@ -103,31 +103,61 @@ const mapChainsToOptions = (chains: Chain[]): Options[] => { })); }; +const CUSTOM_CHAINS_LOCAL_STORAGE_KEY = "customChains"; const getStoredChains = (): Options[] => { if (typeof window !== "undefined") { - const storedChains = localStorage.getItem("customChains"); + const storedChains = localStorage.getItem(CUSTOM_CHAINS_LOCAL_STORAGE_KEY); return storedChains ? JSON.parse(storedChains) : []; } return []; }; +const isChainStored = (chain: Options): boolean => { + const storedChains = getStoredChains(); + return storedChains.some(storedChain => storedChain.value === chain.value); +}; + const networkIds = new Set(networks.map(network => network.id)); const { Option } = components; -const IconOption = (props: OptionProps) => ( - -); + +type CustomOptionProps = OptionProps & { + onDelete: (chain: Options) => void; +}; +const CustomOption = (props: CustomOptionProps) => { + const { data } = props; + const handleDelete = (e: React.MouseEvent) => { + e.stopPropagation(); + props.onDelete(data); + }; + + return ( + + ); +}; export const NetworksDropdown = ({ onChange }: { onChange: (options: any) => any }) => { const [isMobile, setIsMobile] = useState(false); const { resolvedTheme } = useTheme(); - const [selectedOption, setSelectedOption] = useState>(groupedOptions.mainnet.options[0]); + const [selectedOption, setSelectedOption] = useState>(initialGroupedOptions.mainnet.options[0]); const [searchTerm, setSearchTerm] = useState(""); + const [groupedOptions, setGroupedOptions] = useState(initialGroupedOptions); const searchInputRef = useRef(null); const seeAllModalRef = useRef(null); @@ -141,10 +171,11 @@ export const NetworksDropdown = ({ onChange }: { onChange: (options: any) => any const customChains = getStoredChains(); customChains.forEach((chain: Options) => { const groupName = chain.isTestnet ? "testnet" : "mainnet"; - if (!groupedOptions[groupName].options.some(option => option.value === chain.value)) { - groupedOptions[groupName].options.push(chain); + if (!initialGroupedOptions[groupName].options.some(option => option.value === chain.value)) { + initialGroupedOptions[groupName].options.push(chain); } }); + setGroupedOptions({ ...initialGroupedOptions }); }, []); useEffect(() => { @@ -176,7 +207,8 @@ export const NetworksDropdown = ({ onChange }: { onChange: (options: any) => any groupedOptions[groupName].options.push(option); } const customChains = [...getStoredChains(), option]; - localStorage.setItem("customChains", JSON.stringify(customChains)); + localStorage.setItem(CUSTOM_CHAINS_LOCAL_STORAGE_KEY, JSON.stringify(customChains)); + setGroupedOptions({ ...groupedOptions }); setSelectedOption(option); onChange(option); if (seeAllModalRef.current) { @@ -206,6 +238,28 @@ export const NetworksDropdown = ({ onChange }: { onChange: (options: any) => any `${chain.label} ${chain.value}`.toLowerCase().includes(searchTerm.toLowerCase()), ); + const handleDeleteCustomChain = (chain: Options) => { + const updatedChains = getStoredChains().filter((c: Options) => c.value !== chain.value); + + if (typeof window !== "undefined") { + localStorage.setItem(CUSTOM_CHAINS_LOCAL_STORAGE_KEY, JSON.stringify(updatedChains)); + } + + const updatedGroupedOptions = { ...groupedOptions }; + Object.keys(updatedGroupedOptions).forEach(groupName => { + updatedGroupedOptions[groupName as keyof GroupedOptions].options = updatedGroupedOptions[ + groupName as keyof GroupedOptions + ].options.filter(option => option.value !== chain.value); + }); + + setGroupedOptions(updatedGroupedOptions); + + if (selectedOption?.value === chain.value) { + setSelectedOption(updatedGroupedOptions.mainnet.options[0]); + onChange(updatedGroupedOptions.mainnet.options[0]); + } + }; + if (!mounted) return
; return ( @@ -216,7 +270,7 @@ export const NetworksDropdown = ({ onChange }: { onChange: (options: any) => any instanceId="network-select" options={Object.values(groupedOptions)} onChange={handleSelectChange} - components={{ Option: IconOption }} + components={{ Option: props => }} isSearchable={!isMobile} className="max-w-xs relative text-sm w-44" theme={theme => ({