diff --git a/.changeset/tough-buttons-speak.md b/.changeset/tough-buttons-speak.md new file mode 100644 index 000000000..fd943297f --- /dev/null +++ b/.changeset/tough-buttons-speak.md @@ -0,0 +1,5 @@ +--- +"nostrudel": minor +--- + +Add user likes tab under profile view diff --git a/src/app.tsx b/src/app.tsx index da9679389..675eda6cd 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -34,6 +34,7 @@ import UserMediaTab from "./views/user/media"; import ToolsHomeView from "./views/tools"; import Nip19ToolsView from "./views/tools/nip19"; import UserAboutTab from "./views/user/about"; +import UserLikesTab from "./views/user/likes"; const LiveStreamsTab = React.lazy(() => import("./views/streams")); const StreamView = React.lazy(() => import("./views/streams/stream")); @@ -73,6 +74,7 @@ const router = createHashRouter([ { path: "notes", element: }, { path: "media", element: }, { path: "zaps", element: }, + { path: "likes", element: }, { path: "followers", element: }, { path: "following", element: }, { path: "relays", element: }, diff --git a/src/views/user/index.tsx b/src/views/user/index.tsx index 031c4c979..0ef57dfb9 100644 --- a/src/views/user/index.tsx +++ b/src/views/user/index.tsx @@ -46,6 +46,7 @@ const tabs = [ { label: "Media", path: "media" }, { label: "Zaps", path: "zaps" }, { label: "Following", path: "following" }, + { label: "Likes", path: "likes" }, { label: "Relays", path: "relays" }, { label: "Reports", path: "reports" }, { label: "Followers", path: "followers" }, diff --git a/src/views/user/likes.tsx b/src/views/user/likes.tsx new file mode 100644 index 000000000..495c63f30 --- /dev/null +++ b/src/views/user/likes.tsx @@ -0,0 +1,79 @@ +import { useRef } from "react"; +import { useOutletContext } from "react-router-dom"; +import { Box, Flex, SkeletonText, Spacer, Text } from "@chakra-ui/react"; +import { Kind } from "nostr-tools"; +import { getReferences, truncatedId } from "../../helpers/nostr-event"; +import { useTimelineLoader } from "../../hooks/use-timeline-loader"; +import { NostrEvent } from "../../types/nostr-event"; +import { useAdditionalRelayContext } from "../../providers/additional-relay-context"; +import { useReadRelayUrls } from "../../hooks/use-client-relays"; +import TimelineActionAndStatus from "../../components/timeline-action-and-status"; +import useSubject from "../../hooks/use-subject"; +import IntersectionObserverProvider, { useRegisterIntersectionEntity } from "../../providers/intersection-observer"; +import { useTimelineCurserIntersectionCallback } from "../../hooks/use-timeline-cursor-intersection-callback"; +import useSingleEvent from "../../hooks/use-single-event"; +import { Note } from "../../components/note"; +import { TrustProvider } from "../../providers/trust"; +import { UserAvatar } from "../../components/user-avatar"; +import { UserLink } from "../../components/user-link"; +import { NoteMenu } from "../../components/note/note-menu"; + +const Like = ({ event }: { event: NostrEvent }) => { + const ref = useRef(null); + useRegisterIntersectionEntity(ref, event.id); + + const contextRelays = useAdditionalRelayContext(); + const readRelays = useReadRelayUrls(contextRelays); + + const refs = getReferences(event); + const eventId: string | undefined = refs.events[0]; + const { event: note } = useSingleEvent(eventId, readRelays); + + var content = <>; + if (!note) return ; + + if (note.kind === Kind.Text) { + content = ( + <> + + + + {event.content === "+" ? "liked" : "reacted with " + event.content} + + + + + + + ); + } else content = <>Unknown note type {note.kind}; + + return {content}; +}; + +export default function UserLikesTab() { + const { pubkey } = useOutletContext() as { pubkey: string }; + const contextRelays = useAdditionalRelayContext(); + const readRelays = useReadRelayUrls(contextRelays); + + const timeline = useTimelineLoader(`${truncatedId(pubkey)}-likes`, readRelays, { authors: [pubkey], kinds: [7] }); + + const lines = useSubject(timeline.timeline); + + const scrollBox = useRef(null); + const callback = useTimelineCurserIntersectionCallback(timeline); + + return ( + + + + {lines.map((event) => ( + + ))} + + + + + + ); +}