diff --git a/.changeset/real-dancers-punch.md b/.changeset/real-dancers-punch.md new file mode 100644 index 000000000..8f31606a5 --- /dev/null +++ b/.changeset/real-dancers-punch.md @@ -0,0 +1,5 @@ +--- +"nostrudel": patch +--- + +Only fetch open graph metadata for html urls diff --git a/src/components/open-graph-card.tsx b/src/components/open-graph-card.tsx index b61498799..8da40c248 100644 --- a/src/components/open-graph-card.tsx +++ b/src/components/open-graph-card.tsx @@ -15,7 +15,7 @@ export default function OpenGraphCard({ url, ...props }: { url: URL } & Omit {data.ogImage?.map((ogImage) => ( - + ))} diff --git a/src/hooks/use-open-graph-data.ts b/src/hooks/use-open-graph-data.ts index 974329523..40ee59c81 100644 --- a/src/hooks/use-open-graph-data.ts +++ b/src/hooks/use-open-graph-data.ts @@ -2,11 +2,22 @@ import { useAsync } from "react-use"; import extractMetaTags from "../lib/open-graph-scraper/extract"; import { fetchWithCorsFallback } from "../helpers/cors"; +const pageExtensions = [".html", ".php", "htm"]; + export default function useOpenGraphData(url: URL) { return useAsync(async () => { + const controller = new AbortController(); + const ext = url.pathname.match(/\.[\w+d]+$/)?.[0]; + if (ext && !pageExtensions.includes(ext)) return null; + try { - const html = await fetchWithCorsFallback(url).then((res) => res.text()); - return extractMetaTags(html); + const res = await fetchWithCorsFallback(url, { signal: controller.signal }); + const contentType = res.headers.get("content-type"); + + if (contentType?.includes("text/html")) { + const html = await res.text(); + return extractMetaTags(html); + } else controller.abort(); } catch (e) {} return null; }, [url.toString()]); diff --git a/src/services/signing.tsx b/src/services/signing.tsx index f2b965012..c24cf6bad 100644 --- a/src/services/signing.tsx +++ b/src/services/signing.tsx @@ -1,7 +1,7 @@ import { DraftNostrEvent, NostrEvent } from "../types/nostr-event"; import { Account } from "./account"; import db from "./db"; -import { nip04, signEvent, getEventHash, getPublicKey } from "nostr-tools"; +import { nip04, getPublicKey, finishEvent } from "nostr-tools"; const decryptedKeys = new Map(); @@ -85,12 +85,7 @@ class SigningService { } else if (account?.secKey) { const secKey = await this.decryptSecKey(account); const tmpDraft = { ...draft, pubkey: getPublicKey(secKey) }; - const signature = signEvent(tmpDraft, secKey); - const event: NostrEvent = { - ...tmpDraft, - id: getEventHash(tmpDraft), - sig: signature, - }; + const event = finishEvent(tmpDraft, secKey) as NostrEvent; return event; } else throw new Error("No signing method"); diff --git a/src/views/search/index.tsx b/src/views/search/index.tsx index dcffc807c..c1dd84bbf 100644 --- a/src/views/search/index.tsx +++ b/src/views/search/index.tsx @@ -12,10 +12,10 @@ import { useDisclosure, } from "@chakra-ui/react"; import dayjs from "dayjs"; -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import { useSearchParams, Link as RouterLink, useNavigate } from "react-router-dom"; import { useAsync } from "react-use"; -import { LightningIcon, QrCodeIcon } from "../../components/icons"; +import { ClipboardIcon, LightningIcon, QrCodeIcon } from "../../components/icons"; import { UserAvatarLink } from "../../components/user-avatar-link"; import { UserDnsIdentityIcon } from "../../components/user-dns-identity-icon"; import ZapModal from "../../components/zap-modal"; @@ -98,6 +98,10 @@ export default function SearchView() { } }; + const readClipboard = useCallback(async () => { + handleSearchText(await navigator.clipboard.readText()); + }, []); + // set the search when the form is submitted const handleSubmit = (e: React.SyntheticEvent) => { e.preventDefault(); @@ -122,6 +126,9 @@ export default function SearchView() {
} aria-label="Qr Scanner" /> + {!!navigator.clipboard.readText && ( + } aria-label="Read clipboard" /> + )} setSearch(e.target.value)} />