mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-03-29 11:12:12 +01:00
Improve display of unknown events
This commit is contained in:
parent
5ba0bc4f0f
commit
7640beb0c2
5
.changeset/great-terms-flash.md
Normal file
5
.changeset/great-terms-flash.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"nostrudel": minor
|
||||
---
|
||||
|
||||
Improve display of unknown events
|
@ -1,27 +1,109 @@
|
||||
import { useMemo } from "react";
|
||||
import { Box, Button, Card, CardBody, CardHeader, CardProps, Flex, Link, Text, useDisclosure } from "@chakra-ui/react";
|
||||
import { MouseEventHandler, useCallback, useMemo } from "react";
|
||||
import {
|
||||
Box,
|
||||
BoxProps,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
CardProps,
|
||||
Flex,
|
||||
IconButton,
|
||||
Link,
|
||||
Text,
|
||||
useDisclosure,
|
||||
} from "@chakra-ui/react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { nip19 } from "nostr-tools";
|
||||
|
||||
import { getSharableEventAddress } from "../../../helpers/nip19";
|
||||
import { NostrEvent } from "../../../types/nostr-event";
|
||||
import { NostrEvent, Tag, isATag, isETag, isPTag } from "../../../types/nostr-event";
|
||||
import UserAvatarLink from "../../user-avatar-link";
|
||||
import UserLink from "../../user-link";
|
||||
import { truncatedId } from "../../../helpers/nostr/events";
|
||||
import { aTagToAddressPointer, eTagToEventPointer } from "../../../helpers/nostr/events";
|
||||
import { buildAppSelectUrl } from "../../../helpers/nostr/apps";
|
||||
import { UserDnsIdentityIcon } from "../../user-dns-identity-icon";
|
||||
import {
|
||||
embedEmoji,
|
||||
embedNostrHashtags,
|
||||
embedNostrLinks,
|
||||
embedNostrMentions,
|
||||
renderGenericUrl,
|
||||
renderImageUrl,
|
||||
renderVideoUrl,
|
||||
} from "../../embed-types";
|
||||
import { EmbedableContent, embedUrls } from "../../../helpers/embeds";
|
||||
import Timestamp from "../../timestamp";
|
||||
import { CodeIcon } from "../../icons";
|
||||
import { CodeIcon, ExternalLinkIcon } from "../../icons";
|
||||
import NoteDebugModal from "../../debug-modals/note-debug-modal";
|
||||
import { renderAudioUrl } from "../../embed-types/audio";
|
||||
import { EmbedEventPointer } from "..";
|
||||
|
||||
function EventTag({ tag }: { tag: Tag }) {
|
||||
const expand = useDisclosure();
|
||||
const content = `[${tag[0]}] ${tag.slice(1).join(", ")}`;
|
||||
const props = {
|
||||
fontWeight: "bold",
|
||||
fontFamily: "monospace",
|
||||
fontSize: "1.2em",
|
||||
isTruncated: true,
|
||||
color: "GrayText",
|
||||
};
|
||||
|
||||
const toggle = useCallback<MouseEventHandler>(
|
||||
(e) => {
|
||||
e.preventDefault();
|
||||
expand.onToggle();
|
||||
},
|
||||
[expand.onToggle],
|
||||
);
|
||||
|
||||
if (isETag(tag) && tag[1]) {
|
||||
const pointer = eTagToEventPointer(tag);
|
||||
return (
|
||||
<>
|
||||
<Link as={RouterLink} to={`/l/${nip19.neventEncode(pointer)}`} onClick={toggle} {...props}>
|
||||
{content}
|
||||
</Link>
|
||||
{expand.isOpen && <EmbedEventPointer pointer={{ type: "nevent", data: pointer }} />}
|
||||
</>
|
||||
);
|
||||
} else if (isATag(tag) && tag[1]) {
|
||||
const pointer = aTagToAddressPointer(tag);
|
||||
return (
|
||||
<>
|
||||
<Link as={RouterLink} to={`/l/${nip19.naddrEncode(pointer)}`} onClick={toggle} {...props}>
|
||||
{content}
|
||||
</Link>
|
||||
{expand.isOpen && <EmbedEventPointer pointer={{ type: "naddr", data: pointer }} />}
|
||||
</>
|
||||
);
|
||||
} else if (isPTag(tag) && tag[1]) {
|
||||
const pubkey = tag[1];
|
||||
return (
|
||||
<>
|
||||
<Link as={RouterLink} to={`/l/${nip19.npubEncode(pubkey)}`} onClick={toggle} {...props}>
|
||||
{content}
|
||||
</Link>
|
||||
{expand.isOpen && (
|
||||
<Flex gap="4" p="2">
|
||||
<UserAvatarLink pubkey={pubkey} />
|
||||
<Box>
|
||||
<UserLink pubkey={pubkey} fontWeight="bold" />
|
||||
<br />
|
||||
<UserDnsIdentityIcon pubkey={pubkey} />
|
||||
</Box>
|
||||
</Flex>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} else
|
||||
return (
|
||||
<Text title={content} {...props}>
|
||||
{content}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
export default function EmbeddedUnknown({ event, ...props }: Omit<CardProps, "children"> & { event: NostrEvent }) {
|
||||
const debugModal = useDisclosure();
|
||||
@ -29,16 +111,15 @@ export default function EmbeddedUnknown({ event, ...props }: Omit<CardProps, "ch
|
||||
|
||||
const alt = event.tags.find((t) => t[0] === "alt")?.[1];
|
||||
const content = useMemo(() => {
|
||||
let jsx: EmbedableContent = [alt || event.content];
|
||||
let jsx: EmbedableContent = [event.content];
|
||||
jsx = embedNostrLinks(jsx);
|
||||
jsx = embedNostrMentions(jsx, event);
|
||||
jsx = embedNostrHashtags(jsx, event);
|
||||
jsx = embedEmoji(jsx, event);
|
||||
|
||||
jsx = embedUrls(jsx, [renderImageUrl, renderVideoUrl, renderAudioUrl, renderGenericUrl]);
|
||||
|
||||
return jsx;
|
||||
}, [event.content, alt]);
|
||||
}, [event.content]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -47,23 +128,41 @@ export default function EmbeddedUnknown({ event, ...props }: Omit<CardProps, "ch
|
||||
<UserAvatarLink pubkey={event.pubkey} size="xs" />
|
||||
<UserLink pubkey={event.pubkey} isTruncated fontWeight="bold" fontSize="md" />
|
||||
<UserDnsIdentityIcon pubkey={event.pubkey} onlyIcon />
|
||||
<Link ml="auto" href={address ? buildAppSelectUrl(address) : ""} isExternal>
|
||||
<Timestamp timestamp={event.created_at} />
|
||||
</Link>
|
||||
<Text>kind: {event.kind}</Text>
|
||||
<Timestamp timestamp={event.created_at} />
|
||||
<ButtonGroup ml="auto">
|
||||
<Button
|
||||
as={Link}
|
||||
size="sm"
|
||||
leftIcon={<ExternalLinkIcon />}
|
||||
isExternal
|
||||
href={address ? buildAppSelectUrl(address) : ""}
|
||||
>
|
||||
Open
|
||||
</Button>
|
||||
<IconButton
|
||||
icon={<CodeIcon />}
|
||||
aria-label="Raw Event"
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onClick={debugModal.onOpen}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
</CardHeader>
|
||||
<CardBody p="2">
|
||||
<Flex gap="2">
|
||||
<Text>Kind: {event.kind}</Text>
|
||||
<Link href={address ? buildAppSelectUrl(address) : ""} isExternal color="blue.500">
|
||||
{address && truncatedId(address)}
|
||||
</Link>
|
||||
<Button leftIcon={<CodeIcon />} ml="auto" size="sm" variant="outline" onClick={debugModal.onOpen}>
|
||||
View Raw
|
||||
</Button>
|
||||
</Flex>
|
||||
<Box whiteSpace="pre-wrap" noOfLines={5}>
|
||||
{alt && (
|
||||
<Text isTruncated fontStyle="italic">
|
||||
{alt}
|
||||
</Text>
|
||||
)}
|
||||
<Box whiteSpace="pre-wrap" noOfLines={3}>
|
||||
{content}
|
||||
</Box>
|
||||
<Flex direction="column" gap="1" px="2" my="2">
|
||||
{event.tags.map((tag, i) => (
|
||||
<EventTag key={i} tag={tag} />
|
||||
))}
|
||||
</Flex>
|
||||
</CardBody>
|
||||
</Card>
|
||||
{debugModal.isOpen && <NoteDebugModal isOpen={debugModal.isOpen} onClose={debugModal.onClose} event={event} />}
|
||||
|
@ -60,7 +60,7 @@ export default function DatabaseSettings() {
|
||||
</h2>
|
||||
<AccordionPanel>
|
||||
<DatabaseStats />
|
||||
<ButtonGroup>
|
||||
<ButtonGroup mt="2">
|
||||
<Button onClick={handleClearData} isLoading={clearing} isDisabled={clearing}>
|
||||
Clear cache data
|
||||
</Button>
|
||||
|
Loading…
x
Reference in New Issue
Block a user