add link to nostr army knife

This commit is contained in:
hzrd149 2023-06-06 17:26:45 -04:00
parent 6930749ba3
commit 305f5e2922
7 changed files with 87 additions and 24 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": patch
---
Correctly handle web+nostr: links in search

View File

@ -0,0 +1,5 @@
---
"nostrudel": minor
---
Add link to nostr army knife tool

View File

@ -13,7 +13,7 @@ export default function NostrLinkView() {
</Alert>
);
const cleanLink = link.replace(/(web\+)?nostr:/, "");
const cleanLink = link.replace(/(web\+)?nostr:(\/\/)?/, "");
const decoded = nip19.decode(cleanLink);
switch (decoded.type) {

View File

@ -15,8 +15,7 @@ function useNotePointer() {
case "note":
return { id: pointer.data as string, relays: [] };
case "nevent":
const p = pointer.data as nip19.EventPointer;
return { id: p.id, relays: p.relays ?? [] };
return { id: pointer.data.id, relays: pointer.data.relays ?? [] };
default:
throw new Error(`Unknown type ${pointer.type}`);
}

View File

@ -88,14 +88,18 @@ export default function SearchView() {
setSearch(searchParams.get("q") ?? "");
}, [searchParams]);
const handleSearchText = (text: string) => {
if (text.startsWith("nostr:") || text.startsWith("web+nostr:") || safeDecode(search)) {
navigate({ pathname: "/l/" + encodeURIComponent(text) }, { replace: true });
} else {
setSearchParams({ q: text }, { replace: true });
}
};
// set the search when the form is submitted
const handleSubmit = (e: React.SyntheticEvent) => {
e.preventDefault();
if (search.startsWith("nostr:") || safeDecode(search)) {
navigate({ pathname: "/l/" + search }, { replace: true });
} else {
setSearchParams({ q: search }, { replace: true });
}
handleSearchText(search);
};
// fetch search data from nostr.band
@ -107,14 +111,7 @@ export default function SearchView() {
}, [searchParams.get("q")]);
// handle data from qr code scanner
const handleQrCodeData = (text: string) => {
// if its a nostr: link pass it on the the link handler
if (text.startsWith("nostr:")) {
navigate({ pathname: "/l", search: `q=${text}` }, { replace: true });
} else {
setSearchParams({ q: text }, { replace: true });
}
};
const handleQrCodeData = handleSearchText;
return (
<Flex direction="column" overflowX="hidden" overflowY="auto" height="100%" p="2" gap="2">

View File

@ -1,4 +1,4 @@
import { Button, Flex, Heading } from "@chakra-ui/react";
import { Avatar, Button, Flex, Heading, Image, Link } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { ToolsIcon } from "../../components/icons";
@ -8,7 +8,16 @@ export default function ToolsHomeView() {
<Heading>
<ToolsIcon /> Tools
</Heading>
<Flex wrap="wrap">
<Flex wrap="wrap" gap="4">
<Button
as={Link}
href="https://nak.nostr.com/"
isExternal
target="_blank"
leftIcon={<Image src="https://nak.nostr.com/favicon.ico" h="1.5em" />}
>
nostr army knife
</Button>
<Button as={RouterLink} to="./nip19">
Nip-19 encode/decode
</Button>

View File

@ -2,6 +2,7 @@ import {
Button,
Card,
CardBody,
Code,
Flex,
FormControl,
FormErrorMessage,
@ -31,7 +32,7 @@ function EncodeForm() {
const [output, setOutput] = useState("");
const convert = handleSubmit((values) => {
const encode = handleSubmit((values) => {
try {
const pubkey = normalizeToHex(values.pubkey);
if (!pubkey) throw new Error("bad pubkey");
@ -51,24 +52,24 @@ function EncodeForm() {
});
return (
<Card>
<Card size="sm">
<CardBody>
<form onSubmit={convert}>
<form onSubmit={encode}>
<FormControl isInvalid={!!formState.errors.pubkey}>
<FormLabel>Public key</FormLabel>
<Input {...register("pubkey", { minLength: 8 })} placeholder="npub or hex" />
<Input {...register("pubkey", { minLength: 8, required: true })} placeholder="npub or hex" />
{formState.errors.pubkey && <FormErrorMessage>{formState.errors.pubkey.message}</FormErrorMessage>}
</FormControl>
<FormControl isInvalid={!!formState.errors.pubkey}>
<FormLabel>Relay url</FormLabel>
<RelayUrlInput
{...register("relay")}
{...register("relay", { required: true })}
onChange={(v) => setValue("relay", v)}
placeholder="wss://relay.example.com"
/>
{formState.errors.pubkey && <FormErrorMessage>{formState.errors.pubkey.message}</FormErrorMessage>}
<Button type="submit">Encode</Button>
</FormControl>
<Button type="submit">Encode</Button>
</form>
{output && <RawValue heading="nprofile" value={output} />}
</CardBody>
@ -76,6 +77,51 @@ function EncodeForm() {
);
}
function DecodeForm() {
const toast = useToast();
const { handleSubmit, register, formState, setValue } = useForm({
mode: "onBlur",
defaultValues: {
input: "",
},
});
const [output, setOutput] = useState<Object>();
const decode = handleSubmit((values) => {
try {
setOutput(nip19.decode(values.input));
} catch (e) {
if (e instanceof Error) {
toast({ description: e.message });
}
}
});
return (
<Card size="sm">
<CardBody>
<form onSubmit={decode}>
<FormControl isInvalid={!!formState.errors.input}>
<FormLabel>Encoded id</FormLabel>
<Input
{...register("input", { minLength: 8, required: true })}
placeholder="npub, note1, nevent, nprofile..."
/>
{formState.errors.input && <FormErrorMessage>{formState.errors.input.message}</FormErrorMessage>}
</FormControl>
<Button type="submit">Decode</Button>
</form>
{output && (
<Code whiteSpace="pre" overflowX="auto" width="100%">
{JSON.stringify(output, null, 2)}
</Code>
)}
</CardBody>
</Card>
);
}
export default function Nip19ToolsView() {
return (
<Flex direction="column" gap="4" p="4">
@ -84,6 +130,8 @@ export default function Nip19ToolsView() {
</Heading>
<Heading size="sm">Encode</Heading>
<EncodeForm />
<Heading size="sm">Decode</Heading>
<DecodeForm />
</Flex>
);
}