mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-26 17:52:18 +01:00
added slightly better relay picker
This commit is contained in:
parent
b9b81793e4
commit
5976315595
@ -1,10 +1,95 @@
|
||||
import { Input, InputProps } from "@chakra-ui/react";
|
||||
import {
|
||||
Badge,
|
||||
Box,
|
||||
Button,
|
||||
Flex,
|
||||
Highlight,
|
||||
IconButton,
|
||||
Input,
|
||||
InputGroup,
|
||||
InputLeftElement,
|
||||
InputProps,
|
||||
InputRightElement,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
ModalProps,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { useState } from "react";
|
||||
import { useAsync } from "react-use";
|
||||
import { unique } from "../helpers/array";
|
||||
import { RelayIcon, SearchIcon } from "./icons";
|
||||
|
||||
function RelayPickerModal({
|
||||
onSelect,
|
||||
onClose,
|
||||
...props
|
||||
}: { onSelect: (relay: string) => void } & Omit<ModalProps, "children">) {
|
||||
const [search, setSearch] = useState("");
|
||||
const { value: onlineRelays } = useAsync(async () =>
|
||||
fetch("https://api.nostr.watch/v1/online").then((res) => res.json() as Promise<string[]>)
|
||||
);
|
||||
const { value: paidRelays } = useAsync(async () =>
|
||||
fetch("https://api.nostr.watch/v1/paid").then((res) => res.json() as Promise<string[]>)
|
||||
);
|
||||
const relayList = unique(onlineRelays ?? []);
|
||||
|
||||
const filteredRelays = search ? relayList.filter((url) => url.includes(search)) : relayList;
|
||||
|
||||
return (
|
||||
<Modal onClose={onClose} {...props}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader>Pick Relay</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody pt="0" px="4" pb="4">
|
||||
<InputGroup mb="2">
|
||||
<InputLeftElement pointerEvents="none" children={<SearchIcon />} />
|
||||
<Input
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
name="relay-search"
|
||||
value={search}
|
||||
onChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</InputGroup>
|
||||
<Flex gap="2" direction="column">
|
||||
{filteredRelays.map((url) => (
|
||||
<Flex gap="2" alignItems="center">
|
||||
<Button
|
||||
key={url}
|
||||
value={url}
|
||||
onClick={() => {
|
||||
onSelect(url);
|
||||
onClose();
|
||||
}}
|
||||
variant="outline"
|
||||
size="sm"
|
||||
>
|
||||
{url}
|
||||
</Button>
|
||||
{paidRelays?.includes(url) && <Badge colorScheme="green">Paid</Badge>}
|
||||
</Flex>
|
||||
))}
|
||||
</Flex>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
export type RelayUrlInputProps = Omit<InputProps, "type">;
|
||||
|
||||
export const RelayUrlInput = ({ ...props }: RelayUrlInputProps) => {
|
||||
export const RelayUrlInput = ({
|
||||
onChange,
|
||||
...props
|
||||
}: Omit<RelayUrlInputProps, "onChange"> & { onChange: (url: string) => void }) => {
|
||||
const { isOpen, onClose, onOpen } = useDisclosure();
|
||||
const { value: relaysJson } = useAsync(async () =>
|
||||
fetch("https://api.nostr.watch/v1/online").then((res) => res.json() as Promise<string[]>)
|
||||
);
|
||||
@ -12,14 +97,20 @@ export const RelayUrlInput = ({ ...props }: RelayUrlInputProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Input list="relay-suggestions" type="url" {...props} />
|
||||
<datalist id="relay-suggestions">
|
||||
{relaySuggestions.map((url) => (
|
||||
<option key={url} value={url}>
|
||||
{url}
|
||||
</option>
|
||||
))}
|
||||
</datalist>
|
||||
<InputGroup>
|
||||
<Input list="relay-suggestions" type="url" onChange={(e) => onChange(e.target.value)} {...props} />
|
||||
<datalist id="relay-suggestions">
|
||||
{relaySuggestions.map((url) => (
|
||||
<option key={url} value={url}>
|
||||
{url}
|
||||
</option>
|
||||
))}
|
||||
</datalist>
|
||||
<InputRightElement>
|
||||
<IconButton icon={<RelayIcon />} aria-label="Pick from list" size="sm" onClick={onOpen} />
|
||||
</InputRightElement>
|
||||
</InputGroup>
|
||||
<RelayPickerModal onClose={onClose} isOpen={isOpen} onSelect={(url) => onChange(url)} size="2xl" />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -121,7 +121,7 @@ export default function LoginNip05View() {
|
||||
placeholder="wss://nostr.example.com"
|
||||
isRequired
|
||||
value={relayUrl}
|
||||
onChange={(e) => setRelayUrl(e.target.value)}
|
||||
onChange={(url) => setRelayUrl(url)}
|
||||
/>
|
||||
<FormHelperText>The first relay to connect to.</FormHelperText>
|
||||
</FormControl>
|
||||
|
@ -46,7 +46,7 @@ export default function LoginNpubView() {
|
||||
placeholder="wss://nostr.example.com"
|
||||
isRequired
|
||||
value={relayUrl}
|
||||
onChange={(e) => setRelayUrl(e.target.value)}
|
||||
onChange={(url) => setRelayUrl(url)}
|
||||
/>
|
||||
<FormHelperText>The first relay to connect to.</FormHelperText>
|
||||
</FormControl>
|
||||
|
@ -137,7 +137,7 @@ export default function LoginNsecView() {
|
||||
placeholder="wss://nostr.example.com"
|
||||
isRequired
|
||||
value={relayUrl}
|
||||
onChange={(e) => setRelayUrl(e.target.value)}
|
||||
onChange={(url) => setRelayUrl(url)}
|
||||
/>
|
||||
<FormHelperText>The first relay to connect to.</FormHelperText>
|
||||
</FormControl>
|
||||
|
@ -134,7 +134,7 @@ export default function RelaysView() {
|
||||
<RelayUrlInput
|
||||
id="relay-url-input"
|
||||
value={relayInputValue}
|
||||
onChange={(e) => setRelayInputValue(e.target.value)}
|
||||
onChange={(url) => setRelayInputValue(url)}
|
||||
isRequired
|
||||
/>
|
||||
<Button type="submit" isDisabled={saving}>
|
||||
|
Loading…
x
Reference in New Issue
Block a user