mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-09-18 11:32:30 +02:00
Merge branch 'next'
This commit is contained in:
5
.changeset/real-dancers-punch.md
Normal file
5
.changeset/real-dancers-punch.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": patch
|
||||
---
|
||||
|
||||
Only fetch open graph metadata for html urls
|
@@ -15,7 +15,7 @@ export default function OpenGraphCard({ url, ...props }: { url: URL } & Omit<Car
|
||||
return (
|
||||
<LinkBox borderRadius="lg" borderWidth={1} overflow="hidden" {...props}>
|
||||
{data.ogImage?.map((ogImage) => (
|
||||
<Image src={ogImage.url} mx="auto" />
|
||||
<Image key={ogImage.url} src={ogImage.url} mx="auto" />
|
||||
))}
|
||||
|
||||
<Box m="2" mt="4">
|
||||
|
@@ -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()]);
|
||||
|
@@ -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<string, string>();
|
||||
|
||||
@@ -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");
|
||||
|
@@ -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() {
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Flex gap="2">
|
||||
<IconButton onClick={openScanner} icon={<QrCodeIcon />} aria-label="Qr Scanner" />
|
||||
{!!navigator.clipboard.readText && (
|
||||
<IconButton onClick={readClipboard} icon={<ClipboardIcon />} aria-label="Read clipboard" />
|
||||
)}
|
||||
<Input type="search" value={search} onChange={(e) => setSearch(e.target.value)} />
|
||||
<Button type="submit" isLoading={loading}>
|
||||
Search
|
||||
|
Reference in New Issue
Block a user