import cx from "classnames" import React, { useCallback, useEffect, useMemo, useState } from "react" import { NodeData, NodeUpdate } from "src/hooks/node-data" import { ReactComponent as Check } from "src/icons/check.svg" import { ReactComponent as ChevronDown } from "src/icons/chevron-down.svg" import { ReactComponent as Search } from "src/icons/search.svg" const noExitNode = "None" const runAsExitNode = "Run as exit node…" export default function ExitNodeSelector({ className, node, updateNode, }: { className?: string node: NodeData updateNode: (update: NodeUpdate) => Promise | undefined }) { const [open, setOpen] = useState(false) const [selected, setSelected] = useState( node.AdvertiseExitNode ? runAsExitNode : noExitNode ) useEffect(() => { setSelected(node.AdvertiseExitNode ? runAsExitNode : noExitNode) }, [node]) const handleSelect = useCallback( (item: string) => { setOpen(false) if (item === selected) { return // no update } const old = selected setSelected(item) var update: NodeUpdate = {} switch (item) { case noExitNode: // turn off exit node update = { AdvertiseExitNode: false } break case runAsExitNode: // turn on exit node update = { AdvertiseExitNode: true } break } updateNode(update)?.catch(() => setSelected(old)) }, [setOpen, selected, setSelected] ) // TODO: close on click outside // TODO(sonia): allow choosing to use another exit node const [ none, // not using exit nodes advertising, // advertising as exit node using, // using another exit node ] = useMemo( () => [ selected === noExitNode, selected === runAsExitNode, selected !== noExitNode && selected !== runAsExitNode, ], [selected] ) return ( <>
{(advertising || using) && ( )}
{open && (
)} ) } function DropdownSection({ items, selected, onSelect, }: { items: string[] selected?: string onSelect: (item: string) => void }) { return (
{items.map((v) => ( ))}
) }