mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-10-09 20:33:03 +02:00
dont blur images in shared posts
This commit is contained in:
5
.changeset/brown-lies-hide.md
Normal file
5
.changeset/brown-lies-hide.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"nostrudel": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Dont blur images on shared notes
|
@@ -1,51 +0,0 @@
|
|||||||
import { Link as RouterLink } from "react-router-dom";
|
|
||||||
import moment from "moment";
|
|
||||||
import { Card, CardBody, CardHeader, Flex, Heading, Link } from "@chakra-ui/react";
|
|
||||||
import { useIsMobile } from "../hooks/use-is-mobile";
|
|
||||||
import { NoteContents } from "./note/note-contents";
|
|
||||||
import { useUserContacts } from "../hooks/use-user-contacts";
|
|
||||||
import { useCurrentAccount } from "../hooks/use-current-account";
|
|
||||||
import { NostrEvent } from "../types/nostr-event";
|
|
||||||
import { UserAvatarLink } from "./user-avatar-link";
|
|
||||||
import { UserLink } from "./user-link";
|
|
||||||
import { UserDnsIdentityIcon } from "./user-dns-identity";
|
|
||||||
import { Bech32Prefix, normalizeToBech32 } from "../helpers/nip19";
|
|
||||||
import { convertTimestampToDate } from "../helpers/date";
|
|
||||||
import useSubject from "../hooks/use-subject";
|
|
||||||
import appSettings from "../services/app-settings";
|
|
||||||
import EventVerificationIcon from "./event-verification-icon";
|
|
||||||
import { useReadRelayUrls } from "../hooks/use-client-relays";
|
|
||||||
|
|
||||||
const EmbeddedNote = ({ note }: { note: NostrEvent }) => {
|
|
||||||
const account = useCurrentAccount();
|
|
||||||
const { showSignatureVerification } = useSubject(appSettings);
|
|
||||||
|
|
||||||
const readRelays = useReadRelayUrls();
|
|
||||||
const contacts = useUserContacts(account.pubkey, readRelays);
|
|
||||||
const following = contacts?.contacts || [];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card variant="outline">
|
|
||||||
<CardHeader padding="2">
|
|
||||||
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
|
|
||||||
<UserAvatarLink pubkey={note.pubkey} size="xs" />
|
|
||||||
|
|
||||||
<Heading size="sm" display="inline">
|
|
||||||
<UserLink pubkey={note.pubkey} />
|
|
||||||
</Heading>
|
|
||||||
<UserDnsIdentityIcon pubkey={note.pubkey} onlyIcon />
|
|
||||||
<Flex grow={1} />
|
|
||||||
{showSignatureVerification && <EventVerificationIcon event={note} />}
|
|
||||||
<Link as={RouterLink} to={`/n/${normalizeToBech32(note.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
|
|
||||||
{moment(convertTimestampToDate(note.created_at)).fromNow()}
|
|
||||||
</Link>
|
|
||||||
</Flex>
|
|
||||||
</CardHeader>
|
|
||||||
<CardBody p="0">
|
|
||||||
<NoteContents event={note} trusted={following.includes(note.pubkey)} maxHeight={200} />
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default EmbeddedNote;
|
|
43
src/components/note/embeded-note.tsx
Normal file
43
src/components/note/embeded-note.tsx
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { Link as RouterLink } from "react-router-dom";
|
||||||
|
import moment from "moment";
|
||||||
|
import { Card, CardBody, CardHeader, Flex, Heading, Link } from "@chakra-ui/react";
|
||||||
|
import { NoteContents } from "./note-contents";
|
||||||
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
|
import { UserAvatarLink } from "../user-avatar-link";
|
||||||
|
import { UserLink } from "../user-link";
|
||||||
|
import { UserDnsIdentityIcon } from "../user-dns-identity";
|
||||||
|
import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip19";
|
||||||
|
import { convertTimestampToDate } from "../../helpers/date";
|
||||||
|
import useSubject from "../../hooks/use-subject";
|
||||||
|
import appSettings from "../../services/app-settings";
|
||||||
|
import EventVerificationIcon from "../event-verification-icon";
|
||||||
|
import { TrustProvider } from "./trust";
|
||||||
|
|
||||||
|
export default function EmbeddedNote({ note }: { note: NostrEvent }) {
|
||||||
|
const { showSignatureVerification } = useSubject(appSettings);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TrustProvider event={note}>
|
||||||
|
<Card variant="outline">
|
||||||
|
<CardHeader padding="2">
|
||||||
|
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
|
||||||
|
<UserAvatarLink pubkey={note.pubkey} size="xs" />
|
||||||
|
|
||||||
|
<Heading size="sm" display="inline">
|
||||||
|
<UserLink pubkey={note.pubkey} />
|
||||||
|
</Heading>
|
||||||
|
<UserDnsIdentityIcon pubkey={note.pubkey} onlyIcon />
|
||||||
|
<Flex grow={1} />
|
||||||
|
{showSignatureVerification && <EventVerificationIcon event={note} />}
|
||||||
|
<Link as={RouterLink} to={`/n/${normalizeToBech32(note.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
|
||||||
|
{moment(convertTimestampToDate(note.created_at)).fromNow()}
|
||||||
|
</Link>
|
||||||
|
</Flex>
|
||||||
|
</CardHeader>
|
||||||
|
<CardBody p="0">
|
||||||
|
<NoteContents event={note} maxHeight={200} />
|
||||||
|
</CardBody>
|
||||||
|
</Card>
|
||||||
|
</TrustProvider>
|
||||||
|
);
|
||||||
|
}
|
@@ -2,12 +2,7 @@ import React, { useMemo } from "react";
|
|||||||
import { Link as RouterLink } from "react-router-dom";
|
import { Link as RouterLink } from "react-router-dom";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import {
|
import {
|
||||||
Alert,
|
|
||||||
AlertDescription,
|
|
||||||
AlertIcon,
|
|
||||||
AlertTitle,
|
|
||||||
Box,
|
Box,
|
||||||
Button,
|
|
||||||
ButtonGroup,
|
ButtonGroup,
|
||||||
Card,
|
Card,
|
||||||
CardBody,
|
CardBody,
|
||||||
@@ -18,57 +13,29 @@ import {
|
|||||||
Heading,
|
Heading,
|
||||||
IconButton,
|
IconButton,
|
||||||
Link,
|
Link,
|
||||||
Spacer,
|
|
||||||
} from "@chakra-ui/react";
|
} from "@chakra-ui/react";
|
||||||
import { NostrEvent } from "../../types/nostr-event";
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
import { UserAvatarLink } from "../user-avatar-link";
|
import { UserAvatarLink } from "../user-avatar-link";
|
||||||
import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip19";
|
import { Bech32Prefix, normalizeToBech32 } from "../../helpers/nip19";
|
||||||
|
|
||||||
import { NoteContents } from "./note-contents";
|
|
||||||
import { NoteMenu } from "./note-menu";
|
import { NoteMenu } from "./note-menu";
|
||||||
import { useUserContacts } from "../../hooks/use-user-contacts";
|
|
||||||
import { NoteRelays } from "./note-relays";
|
import { NoteRelays } from "./note-relays";
|
||||||
import { useIsMobile } from "../../hooks/use-is-mobile";
|
import { useIsMobile } from "../../hooks/use-is-mobile";
|
||||||
import { UserLink } from "../user-link";
|
import { UserLink } from "../user-link";
|
||||||
import { UserDnsIdentityIcon } from "../user-dns-identity";
|
import { UserDnsIdentityIcon } from "../user-dns-identity";
|
||||||
import { convertTimestampToDate } from "../../helpers/date";
|
import { convertTimestampToDate } from "../../helpers/date";
|
||||||
import { useCurrentAccount } from "../../hooks/use-current-account";
|
|
||||||
import ReactionButton from "./buttons/reaction-button";
|
import ReactionButton from "./buttons/reaction-button";
|
||||||
import NoteZapButton from "./note-zap-button";
|
import NoteZapButton from "./note-zap-button";
|
||||||
import { ExpandProvider, useExpand } from "./expanded";
|
import { ExpandProvider } from "./expanded";
|
||||||
import useSubject from "../../hooks/use-subject";
|
import useSubject from "../../hooks/use-subject";
|
||||||
import appSettings from "../../services/app-settings";
|
import appSettings from "../../services/app-settings";
|
||||||
import EventVerificationIcon from "../event-verification-icon";
|
import EventVerificationIcon from "../event-verification-icon";
|
||||||
import { ReplyButton } from "./buttons/reply-button";
|
import { ReplyButton } from "./buttons/reply-button";
|
||||||
import { RepostButton } from "./buttons/repost-button";
|
import { RepostButton } from "./buttons/repost-button";
|
||||||
import { QuoteRepostButton } from "./buttons/quote-repost-button";
|
import { QuoteRepostButton } from "./buttons/quote-repost-button";
|
||||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
|
||||||
import { ExternalLinkIcon } from "../icons";
|
import { ExternalLinkIcon } from "../icons";
|
||||||
import SensitiveContentWarning from "../sensitive-content-warning";
|
import NoteContentWithWarning from "./note-content-with-warning";
|
||||||
import useAppSettings from "../../hooks/use-app-settings";
|
import { TrustProvider } from "./trust";
|
||||||
|
|
||||||
function NoteContentWithWarning({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
|
||||||
const account = useCurrentAccount();
|
|
||||||
const expand = useExpand();
|
|
||||||
const settings = useAppSettings();
|
|
||||||
|
|
||||||
const readRelays = useReadRelayUrls();
|
|
||||||
const contacts = useUserContacts(account.pubkey, readRelays);
|
|
||||||
const following = contacts?.contacts || [];
|
|
||||||
|
|
||||||
const contentWarning = event.tags.find((t) => t[0] === "content-warning")?.[1];
|
|
||||||
const showContentWarning = settings.showContentWarning && contentWarning && !expand?.expanded;
|
|
||||||
|
|
||||||
return showContentWarning ? (
|
|
||||||
<SensitiveContentWarning description={contentWarning} />
|
|
||||||
) : (
|
|
||||||
<NoteContents
|
|
||||||
event={event}
|
|
||||||
trusted={event.pubkey === account.pubkey || following.includes(event.pubkey)}
|
|
||||||
maxHeight={maxHeight}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type NoteProps = {
|
export type NoteProps = {
|
||||||
event: NostrEvent;
|
event: NostrEvent;
|
||||||
@@ -83,50 +50,52 @@ export const Note = React.memo(({ event, maxHeight, variant = "outline" }: NoteP
|
|||||||
const externalLink = useMemo(() => event.tags.find((t) => t[0] === "mostr"), [event]);
|
const externalLink = useMemo(() => event.tags.find((t) => t[0] === "mostr"), [event]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ExpandProvider>
|
<TrustProvider event={event}>
|
||||||
<Card variant={variant}>
|
<ExpandProvider>
|
||||||
<CardHeader padding="2">
|
<Card variant={variant}>
|
||||||
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
|
<CardHeader padding="2">
|
||||||
<UserAvatarLink pubkey={event.pubkey} size={isMobile ? "xs" : "sm"} />
|
<Flex flex="1" gap="2" alignItems="center" wrap="wrap">
|
||||||
|
<UserAvatarLink pubkey={event.pubkey} size={isMobile ? "xs" : "sm"} />
|
||||||
|
|
||||||
<Heading size="sm" display="inline">
|
<Heading size="sm" display="inline">
|
||||||
<UserLink pubkey={event.pubkey} />
|
<UserLink pubkey={event.pubkey} />
|
||||||
</Heading>
|
</Heading>
|
||||||
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
||||||
<Flex grow={1} />
|
<Flex grow={1} />
|
||||||
{showSignatureVerification && <EventVerificationIcon event={event} />}
|
{showSignatureVerification && <EventVerificationIcon event={event} />}
|
||||||
<Link as={RouterLink} to={`/n/${normalizeToBech32(event.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
|
<Link as={RouterLink} to={`/n/${normalizeToBech32(event.id, Bech32Prefix.Note)}`} whiteSpace="nowrap">
|
||||||
{moment(convertTimestampToDate(event.created_at)).fromNow()}
|
{moment(convertTimestampToDate(event.created_at)).fromNow()}
|
||||||
</Link>
|
</Link>
|
||||||
</Flex>
|
</Flex>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardBody p="0">
|
<CardBody p="0">
|
||||||
<NoteContentWithWarning event={event} maxHeight={maxHeight} />
|
<NoteContentWithWarning event={event} maxHeight={maxHeight} />
|
||||||
</CardBody>
|
</CardBody>
|
||||||
<CardFooter padding="2" display="flex" gap="2">
|
<CardFooter padding="2" display="flex" gap="2">
|
||||||
<ButtonGroup size="sm" variant="link">
|
<ButtonGroup size="sm" variant="link">
|
||||||
<ReplyButton event={event} />
|
<ReplyButton event={event} />
|
||||||
<RepostButton event={event} />
|
<RepostButton event={event} />
|
||||||
<QuoteRepostButton event={event} />
|
<QuoteRepostButton event={event} />
|
||||||
<NoteZapButton note={event} size="sm" />
|
<NoteZapButton note={event} size="sm" />
|
||||||
{showReactions && <ReactionButton note={event} size="sm" />}
|
{showReactions && <ReactionButton note={event} size="sm" />}
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
<Box flexGrow={1} />
|
<Box flexGrow={1} />
|
||||||
{externalLink && (
|
{externalLink && (
|
||||||
<IconButton
|
<IconButton
|
||||||
as={Link}
|
as={Link}
|
||||||
icon={<ExternalLinkIcon />}
|
icon={<ExternalLinkIcon />}
|
||||||
aria-label="Open External"
|
aria-label="Open External"
|
||||||
href={externalLink[1]}
|
href={externalLink[1]}
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="link"
|
variant="link"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<NoteRelays event={event} size="sm" variant="link" />
|
<NoteRelays event={event} size="sm" variant="link" />
|
||||||
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
|
<NoteMenu event={event} size="sm" variant="link" aria-label="More Options" />
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</ExpandProvider>
|
</ExpandProvider>
|
||||||
|
</TrustProvider>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
20
src/components/note/note-content-with-warning.tsx
Normal file
20
src/components/note/note-content-with-warning.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
|
|
||||||
|
import { NoteContents } from "./note-contents";
|
||||||
|
import { useExpand } from "./expanded";
|
||||||
|
import SensitiveContentWarning from "../sensitive-content-warning";
|
||||||
|
import useAppSettings from "../../hooks/use-app-settings";
|
||||||
|
|
||||||
|
export default function NoteContentWithWarning({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
||||||
|
const expand = useExpand();
|
||||||
|
const settings = useAppSettings();
|
||||||
|
|
||||||
|
const contentWarning = event.tags.find((t) => t[0] === "content-warning")?.[1];
|
||||||
|
const showContentWarning = settings.showContentWarning && contentWarning && !expand?.expanded;
|
||||||
|
|
||||||
|
return showContentWarning ? (
|
||||||
|
<SensitiveContentWarning description={contentWarning} />
|
||||||
|
) : (
|
||||||
|
<NoteContents event={event} maxHeight={maxHeight} />
|
||||||
|
);
|
||||||
|
}
|
@@ -21,8 +21,9 @@ import {
|
|||||||
embedNostrHashtags,
|
embedNostrHashtags,
|
||||||
} from "../embed-types";
|
} from "../embed-types";
|
||||||
import { ImageGalleryProvider } from "../image-gallery";
|
import { ImageGalleryProvider } from "../image-gallery";
|
||||||
|
import { useTrusted } from "./trust";
|
||||||
|
|
||||||
function buildContents(event: NostrEvent | DraftNostrEvent, trusted: boolean = false) {
|
function buildContents(event: NostrEvent | DraftNostrEvent, trusted = false) {
|
||||||
let content: EmbedableContent = [event.content.trim()];
|
let content: EmbedableContent = [event.content.trim()];
|
||||||
|
|
||||||
content = embedLightningInvoice(content);
|
content = embedLightningInvoice(content);
|
||||||
@@ -59,12 +60,12 @@ const GradientOverlay = styled.div`
|
|||||||
|
|
||||||
export type NoteContentsProps = {
|
export type NoteContentsProps = {
|
||||||
event: NostrEvent | DraftNostrEvent;
|
event: NostrEvent | DraftNostrEvent;
|
||||||
trusted?: boolean;
|
|
||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const NoteContents = React.memo(({ event, trusted, maxHeight }: NoteContentsProps) => {
|
export const NoteContents = React.memo(({ event, maxHeight }: NoteContentsProps) => {
|
||||||
const content = buildContents(event, trusted ?? false);
|
const trusted = useTrusted();
|
||||||
|
const content = buildContents(event, trusted);
|
||||||
const expand = useExpand();
|
const expand = useExpand();
|
||||||
const [innerHeight, setInnerHeight] = useState(0);
|
const [innerHeight, setInnerHeight] = useState(0);
|
||||||
const ref = useRef<HTMLDivElement | null>(null);
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||||
import useSingleEvent from "../../hooks/use-single-event";
|
import useSingleEvent from "../../hooks/use-single-event";
|
||||||
import EmbeddedNote from "../embeded-note";
|
import EmbeddedNote from "./embeded-note";
|
||||||
import { NoteLink } from "../note-link";
|
import { NoteLink } from "../note-link";
|
||||||
|
|
||||||
const QuoteNote = ({ noteId, relay }: { noteId: string; relay?: string }) => {
|
const QuoteNote = ({ noteId, relay }: { noteId: string; relay?: string }) => {
|
||||||
|
53
src/components/note/repost-note.tsx
Normal file
53
src/components/note/repost-note.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { Box, Flex, Heading, SkeletonText } from "@chakra-ui/react";
|
||||||
|
import { useAsync } from "react-use";
|
||||||
|
import clientRelaysService from "../../services/client-relays";
|
||||||
|
import singleEventService from "../../services/single-event";
|
||||||
|
import { isETag, NostrEvent } from "../../types/nostr-event";
|
||||||
|
import { ErrorFallback } from "../error-boundary";
|
||||||
|
import { Note } from ".";
|
||||||
|
import { NoteMenu } from "./note-menu";
|
||||||
|
import { UserAvatar } from "../user-avatar";
|
||||||
|
import { UserDnsIdentityIcon } from "../user-dns-identity";
|
||||||
|
import { UserLink } from "../user-link";
|
||||||
|
import { unique } from "../../helpers/array";
|
||||||
|
import { TrustProvider } from "./trust";
|
||||||
|
|
||||||
|
export default function RepostNote({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
||||||
|
const {
|
||||||
|
value: repostNote,
|
||||||
|
loading,
|
||||||
|
error,
|
||||||
|
} = useAsync(async () => {
|
||||||
|
const [_, eventId, relay] = event.tags.find(isETag) ?? [];
|
||||||
|
if (eventId) {
|
||||||
|
const readRelays = clientRelaysService.getReadUrls();
|
||||||
|
if (relay) readRelays.push(relay);
|
||||||
|
return singleEventService.requestEvent(eventId, unique(readRelays));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [event]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TrustProvider event={event}>
|
||||||
|
<Flex gap="2" direction="column">
|
||||||
|
<Flex gap="2" alignItems="center" pl="1">
|
||||||
|
<UserAvatar pubkey={event.pubkey} size="xs" />
|
||||||
|
<Heading size="sm" display="inline">
|
||||||
|
<UserLink pubkey={event.pubkey} />
|
||||||
|
</Heading>
|
||||||
|
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
||||||
|
<span>Shared note</span>
|
||||||
|
<Box flex={1} />
|
||||||
|
<NoteMenu event={event} size="sm" variant="link" aria-label="note options" />
|
||||||
|
</Flex>
|
||||||
|
{loading ? (
|
||||||
|
<SkeletonText />
|
||||||
|
) : repostNote ? (
|
||||||
|
<Note event={repostNote} maxHeight={maxHeight} />
|
||||||
|
) : (
|
||||||
|
<ErrorFallback error={error} />
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
</TrustProvider>
|
||||||
|
);
|
||||||
|
}
|
28
src/components/note/trust.tsx
Normal file
28
src/components/note/trust.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import React, { PropsWithChildren, useContext } from "react";
|
||||||
|
import { NostrEvent } from "../../types/nostr-event";
|
||||||
|
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||||
|
import { useUserContacts } from "../../hooks/use-user-contacts";
|
||||||
|
import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||||
|
|
||||||
|
const TrustContext = React.createContext<boolean>(false);
|
||||||
|
|
||||||
|
export function useTrusted() {
|
||||||
|
return useContext(TrustContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TrustProvider({
|
||||||
|
children,
|
||||||
|
event,
|
||||||
|
trust = false,
|
||||||
|
}: PropsWithChildren & { event?: NostrEvent; trust?: boolean }) {
|
||||||
|
const parentTrust = useContext(TrustContext);
|
||||||
|
|
||||||
|
const account = useCurrentAccount();
|
||||||
|
const readRelays = useReadRelayUrls();
|
||||||
|
const contacts = useUserContacts(account.pubkey, readRelays);
|
||||||
|
const following = contacts?.contacts || [];
|
||||||
|
|
||||||
|
const isEventTrusted = trust || (!!event && (event.pubkey === account.pubkey || following.includes(event.pubkey)));
|
||||||
|
|
||||||
|
return <TrustContext.Provider value={parentTrust || isEventTrusted}>{children}</TrustContext.Provider>;
|
||||||
|
}
|
@@ -27,6 +27,7 @@ import { ImageIcon } from "../icons";
|
|||||||
import { NoteLink } from "../note-link";
|
import { NoteLink } from "../note-link";
|
||||||
import { NoteContents } from "../note/note-contents";
|
import { NoteContents } from "../note/note-contents";
|
||||||
import { PostResults } from "./post-results";
|
import { PostResults } from "./post-results";
|
||||||
|
import { TrustProvider } from "../note/trust";
|
||||||
|
|
||||||
function emptyDraft(): DraftNostrEvent {
|
function emptyDraft(): DraftNostrEvent {
|
||||||
return {
|
return {
|
||||||
@@ -139,7 +140,9 @@ export const PostModal = ({ isOpen, onClose, initialDraft }: PostModalProps) =>
|
|||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
{showPreview ? (
|
{showPreview ? (
|
||||||
<NoteContents event={finalizeNote(draft)} trusted />
|
<TrustProvider trust>
|
||||||
|
<NoteContents event={finalizeNote(draft)} />
|
||||||
|
</TrustProvider>
|
||||||
) : (
|
) : (
|
||||||
<Textarea
|
<Textarea
|
||||||
autoFocus
|
autoFocus
|
||||||
|
@@ -1,50 +0,0 @@
|
|||||||
import { Box, Flex, Heading, SkeletonText } from "@chakra-ui/react";
|
|
||||||
import { useAsync } from "react-use";
|
|
||||||
import clientRelaysService from "../services/client-relays";
|
|
||||||
import singleEventService from "../services/single-event";
|
|
||||||
import { isETag, NostrEvent } from "../types/nostr-event";
|
|
||||||
import { ErrorFallback } from "./error-boundary";
|
|
||||||
import { Note } from "./note";
|
|
||||||
import { NoteMenu } from "./note/note-menu";
|
|
||||||
import { UserAvatar } from "./user-avatar";
|
|
||||||
import { UserDnsIdentityIcon } from "./user-dns-identity";
|
|
||||||
import { UserLink } from "./user-link";
|
|
||||||
import { unique } from "../helpers/array";
|
|
||||||
|
|
||||||
export default function RepostNote({ event, maxHeight }: { event: NostrEvent; maxHeight?: number }) {
|
|
||||||
const {
|
|
||||||
value: repostNote,
|
|
||||||
loading,
|
|
||||||
error,
|
|
||||||
} = useAsync(async () => {
|
|
||||||
const [_, eventId, relay] = event.tags.find(isETag) ?? [];
|
|
||||||
if (eventId) {
|
|
||||||
const readRelays = clientRelaysService.getReadUrls();
|
|
||||||
if (relay) readRelays.push(relay);
|
|
||||||
return singleEventService.requestEvent(eventId, unique(readRelays));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}, [event]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Flex gap="2" direction="column">
|
|
||||||
<Flex gap="2" alignItems="center" pl="1">
|
|
||||||
<UserAvatar pubkey={event.pubkey} size="xs" />
|
|
||||||
<Heading size="sm" display="inline">
|
|
||||||
<UserLink pubkey={event.pubkey} />
|
|
||||||
</Heading>
|
|
||||||
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
|
||||||
<span>Shared note</span>
|
|
||||||
<Box flex={1} />
|
|
||||||
<NoteMenu event={event} size="sm" variant="link" aria-label="note options" />
|
|
||||||
</Flex>
|
|
||||||
{loading ? (
|
|
||||||
<SkeletonText />
|
|
||||||
) : repostNote ? (
|
|
||||||
<Note event={repostNote} maxHeight={maxHeight} />
|
|
||||||
) : (
|
|
||||||
<ErrorFallback error={error} />
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
);
|
|
||||||
}
|
|
@@ -10,7 +10,7 @@ import { useContext } from "react";
|
|||||||
import { PostModalContext } from "../../providers/post-modal-provider";
|
import { PostModalContext } from "../../providers/post-modal-provider";
|
||||||
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
import { useReadRelayUrls } from "../../hooks/use-client-relays";
|
||||||
import { useCurrentAccount } from "../../hooks/use-current-account";
|
import { useCurrentAccount } from "../../hooks/use-current-account";
|
||||||
import RepostNote from "../../components/repost-note";
|
import RepostNote from "../../components/note/repost-note";
|
||||||
|
|
||||||
export default function FollowingTab() {
|
export default function FollowingTab() {
|
||||||
const account = useCurrentAccount();
|
const account = useCurrentAccount();
|
||||||
|
@@ -20,7 +20,7 @@ import moment from "moment";
|
|||||||
import { useOutletContext } from "react-router-dom";
|
import { useOutletContext } from "react-router-dom";
|
||||||
import { RelayIcon } from "../../components/icons";
|
import { RelayIcon } from "../../components/icons";
|
||||||
import { Note } from "../../components/note";
|
import { Note } from "../../components/note";
|
||||||
import RepostNote from "../../components/repost-note";
|
import RepostNote from "../../components/note/repost-note";
|
||||||
import { isReply, isRepost, truncatedId } from "../../helpers/nostr-event";
|
import { isReply, isRepost, truncatedId } from "../../helpers/nostr-event";
|
||||||
import { useTimelineLoader } from "../../hooks/use-timeline-loader";
|
import { useTimelineLoader } from "../../hooks/use-timeline-loader";
|
||||||
import { useAdditionalRelayContext } from "../../providers/additional-relay-context";
|
import { useAdditionalRelayContext } from "../../providers/additional-relay-context";
|
||||||
|
Reference in New Issue
Block a user