This commit is contained in:
zmeyer44 2023-10-16 00:28:09 -04:00
parent 5a3003abe5
commit 3a91d248e9
15 changed files with 173 additions and 101 deletions

View File

@ -42,9 +42,7 @@ export default function ProfilePage({
{!!profile?.banner && ( {!!profile?.banner && (
<Image <Image
className="absolute inset-0 h-full w-full object-cover align-middle" className="absolute inset-0 h-full w-full object-cover align-middle"
src={ src={profile.banner}
"https://images.lumacdn.com/cdn-cgi/image/format=auto,fit=cover,dpr=2,quality=75,width=1250,height=357.14285714285717/calendar-cover-images/4m/c50dff9c-12e1-4b8a-ae95-68a36364b760"
}
width={400} width={400}
height={100} height={100}
alt="banner" alt="banner"
@ -58,9 +56,7 @@ export default function ProfilePage({
<div className="z-1 ml-[calc(-1_*_3px)] overflow-hidden rounded-[0.5rem] bg-background p-[3px] sm:ml-[calc(-1_*_4px)] sm:p-[4px] lg:ml-[calc(-1_*_6px)] lg:rounded-[1rem] lg:p-[6px]"> <div className="z-1 ml-[calc(-1_*_3px)] overflow-hidden rounded-[0.5rem] bg-background p-[3px] sm:ml-[calc(-1_*_4px)] sm:p-[4px] lg:ml-[calc(-1_*_6px)] lg:rounded-[1rem] lg:p-[6px]">
{profile?.image ? ( {profile?.image ? (
<Image <Image
src={ src={profile.image}
"https://images.lumacdn.com/cdn-cgi/image/format=auto,fit=cover,dpr=2,background=white,quality=75,width=96,height=96/calendars/hw/70772773-6d97-4fbb-a076-fc4dee603080"
}
className="aspect-square w-[4rem] overflow-hidden rounded-[calc(0.5rem_-_3px)] object-cover object-center sm:w-[4.5rem] sm:rounded-[calc(0.5rem_-_4px)] md:w-[5rem] lg:w-[6rem] lg:rounded-[calc(1rem_-_6px)]" className="aspect-square w-[4rem] overflow-hidden rounded-[calc(0.5rem_-_3px)] object-cover object-center sm:w-[4.5rem] sm:rounded-[calc(0.5rem_-_4px)] md:w-[5rem] lg:w-[6rem] lg:rounded-[calc(1rem_-_6px)]"
unoptimized unoptimized
alt="profile picture" alt="profile picture"

View File

@ -102,6 +102,7 @@ function Creator({ npub }: { npub: string }) {
"", "",
summary: summary:
getTagValues("summary", e.tags) ?? getTagValues("r", e.tags) ?? e.content, getTagValues("summary", e.tags) ?? getTagValues("r", e.tags) ?? e.content,
href: `/article/${e.encode()}`,
})); }));
return ( return (

View File

@ -12,6 +12,8 @@ import { DUMMY_30023 } from "@/constants";
import Link from "next/link"; import Link from "next/link";
import useEvents from "@/lib/hooks/useEvents"; import useEvents from "@/lib/hooks/useEvents";
import { Event } from "nostr-tools"; import { Event } from "nostr-tools";
import KindLoading from "@/components/KindCard/loading";
export default function LongFormContentSection() { export default function LongFormContentSection() {
const { events } = useEvents({ const { events } = useEvents({
filter: { filter: {
@ -28,14 +30,23 @@ export default function LongFormContentSection() {
</Button> </Button>
</SectionHeader> </SectionHeader>
<SectionContent className="sm:lg-feed-cols relative mx-auto flex flex-col gap-4"> <SectionContent className="sm:lg-feed-cols relative mx-auto flex flex-col gap-4">
{events.map((e) => { {events?.length ? (
events.map((e) => {
const event = e.rawEvent() as Event; const event = e.rawEvent() as Event;
return ( return (
<Link key={e.id} href={`/article/${e.tagId}`}> <Link key={e.id} href={`/article/${e.tagId}`}>
<KindCard {...event} /> <KindCard {...event} />
</Link> </Link>
); );
})} })
) : (
<>
<KindLoading />
<KindLoading />
<KindLoading />
<KindLoading />
</>
)}
</SectionContent> </SectionContent>
</Section> </Section>
); );

View File

@ -1,12 +0,0 @@
"use client";
import Article from "@/containers/Article";
export default function ArticlePage({
params: { eventId },
}: {
params: {
eventId: string;
};
}) {
return <Article />;
}

View File

@ -0,0 +1,39 @@
"use client";
import { useEffect } from "react";
import Article from "@/containers/Article";
import { useNDK } from "@nostr-dev-kit/ndk-react";
import { nip19 } from "nostr-tools";
import Spinner from "@/components/spinner";
import useEvents from "@/lib/hooks/useEvents";
export default function ArticlePage({
params: { naddr },
}: {
params: {
naddr: string;
};
}) {
const { ndk } = useNDK();
const { data, type } = nip19.decode(naddr);
const { events } = useEvents({
filter:
type === "naddr"
? {
kinds: [data.kind],
authors: [data.pubkey],
["#d"]: [data.identifier],
limit: 1,
}
: {},
});
if (events?.[0]) {
return <Article event={events[0]} />;
}
return (
<div className="center pt-20 text-primary">
<Spinner />
{events.length}
</div>
);
}

View File

@ -19,6 +19,7 @@ type CreatorCardProps = {
id: string; id: string;
title: string; title: string;
summary: string; summary: string;
href: string;
}[]; }[];
}; };
@ -39,7 +40,11 @@ export default function CreatorCard({
<div className="absolute inset-0 bg-background/60 backdrop-blur-md transition-all"> <div className="absolute inset-0 bg-background/60 backdrop-blur-md transition-all">
<div className="group relative flex h-full w-full flex-col items-center justify-end transition-all"> <div className="group relative flex h-full w-full flex-col items-center justify-end transition-all">
<CardHeader className="absolute inset-x-0 top-[59%] transform pt-4 text-center transition-all duration-300 group-hover:top-[8px] group-hover:ml-[75px] group-hover:text-left"> <CardHeader className="absolute inset-x-0 top-[59%] transform pt-4 text-center transition-all duration-300 group-hover:top-[8px] group-hover:ml-[75px] group-hover:text-left">
<CardTitle>{getNameToShow({ profile, npub })}</CardTitle> <Link href={`/${npub}`}>
<CardTitle className="hover:underline">
{getNameToShow({ profile, npub })}
</CardTitle>
</Link>
<CardDescription className="line-clamp-3 group-hover:text-xs"> <CardDescription className="line-clamp-3 group-hover:text-xs">
{profile?.about} {profile?.about}
</CardDescription> </CardDescription>
@ -65,7 +70,7 @@ export default function CreatorCard({
{recentWork.map((item) => ( {recentWork.map((item) => (
<li key={item.id} className="w-full overflow-hidden"> <li key={item.id} className="w-full overflow-hidden">
<Link <Link
href={`/${item.id}`} href={item.href}
className="flex max-w-full items-center justify-between overflow-hidden py-1.5 pl-4 pr-2 transition-colors hover:bg-muted hover:text-primary" className="flex max-w-full items-center justify-between overflow-hidden py-1.5 pl-4 pr-2 transition-colors hover:bg-muted hover:text-primary"
> >
<div className="shrink overflow-x-hidden"> <div className="shrink overflow-x-hidden">

View File

@ -14,7 +14,7 @@ export default function Kind30023({ content, pubkey, tags }: Event) {
return ( return (
<Container pubkey={pubkey} contentTags={contentTags}> <Container pubkey={pubkey} contentTags={contentTags}>
<CardTitle className="mb-1.5 line-clamp-2 text-lg font-semibold"> <CardTitle className="mb-1.5 line-clamp-2 text-lg font-semibold leading-6">
{title} {title}
</CardTitle> </CardTitle>
<CardDescription className="line-clamp-4 text-sm"> <CardDescription className="line-clamp-4 text-sm">

View File

@ -37,7 +37,7 @@ export default function Container({
actionOptions = [], actionOptions = [],
}: CreatorCardProps) { }: CreatorCardProps) {
return ( return (
<Card className="relative overflow-hidden"> <Card className="relative flex h-full flex-col overflow-hidden">
<CardHeader className="flex flex-row items-center justify-between space-y-0 p-4 pb-4"> <CardHeader className="flex flex-row items-center justify-between space-y-0 p-4 pb-4">
<ProfileHeader pubkey={pubkey} /> <ProfileHeader pubkey={pubkey} />
<div className="-mr-1 flex items-center gap-x-1.5 text-xs text-muted-foreground"> <div className="-mr-1 flex items-center gap-x-1.5 text-xs text-muted-foreground">
@ -53,14 +53,16 @@ export default function Container({
</DropDownMenu> </DropDownMenu>
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="px-4 pb-3"> <CardContent className="flex grow flex-col px-4 pb-3">
{children} {children}
<div className="mt-auto">
{!!contentTags?.length && ( {!!contentTags?.length && (
<div className="-mb-2 mt-1 max-h-[52px] overflow-hidden"> <div className="-mb-1 mt-1 max-h-[52px] overflow-hidden">
<Tags tags={contentTags} /> <Tags tags={contentTags} />
</div> </div>
)} )}
<Actions /> <Actions />
</div>
</CardContent> </CardContent>
</Card> </Card>
); );

View File

@ -19,12 +19,34 @@ export default function ProfileHeader({ pubkey }: ProfileHeaderProps) {
{getTwoLetters({ npub, profile })} {getTwoLetters({ npub, profile })}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<div className="center 5 gap-1"> {profile?.displayName || profile?.name ? (
<span className="text-xs uppercase text-muted-foreground group-hover:underline"> <div className="flex flex-col gap-0">
<div className="flex items-center gap-1">
<span className="text-sm font-medium text-foreground group-hover:underline">
{getNameToShow({ npub, profile })} {getNameToShow({ npub, profile })}
</span> </span>
{!!profile?.nip05 && <HiCheckBadge className="h-4 w-4 text-primary" />} {!!profile?.nip05 && (
<HiCheckBadge className="h-4 w-4 text-primary" />
)}
</div> </div>
<div className="flex items-center gap-1">
{!!profile.nip05 && (
<span className="text-[11px] text-muted-foreground">
{profile.nip05}
</span>
)}
</div>
</div>
) : (
<div className="flex items-center gap-1">
<span className="text-sm uppercase text-foreground group-hover:underline">
{getNameToShow({ npub, profile })}
</span>
{!!profile?.nip05 && (
<HiCheckBadge className="h-4 w-4 text-primary" />
)}
</div>
)}
</Link> </Link>
); );
} }

View File

@ -0,0 +1,21 @@
import Container from "./components/Container";
import { CardTitle, CardDescription } from "@/components/ui/card";
import { type Event } from "nostr-tools";
import { Skeleton } from "@/components/ui/skeleton";
export default function KindLoading() {
return (
<Container
pubkey={
"f7234bd4c1394dda46d09f35bd384dd30cc552ad5541990f98844fb06676e9ca"
}
>
<div className="space-y-2 text-muted-foreground">
<Skeleton className="mb-2 h-4 w-1/3 bg-muted" />
<Skeleton className="h-4 w-1/2 bg-muted" />
<Skeleton className="h-4 w-2/5 bg-muted" />
<Skeleton className="h-4 w-4/5 bg-muted" />
</div>
</Container>
);
}

View File

@ -12,7 +12,6 @@ type MarkdoneProps = {
}; };
export default function Markdown({ content }: MarkdoneProps) { export default function Markdown({ content }: MarkdoneProps) {
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
// const [blocks, setBlocks] = useState<Block[]>();
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const editor: BlockNoteEditor = useBlockNote({ const editor: BlockNoteEditor = useBlockNote({
@ -22,12 +21,10 @@ export default function Markdown({ content }: MarkdoneProps) {
useEffect(() => { useEffect(() => {
if (editor) { if (editor) {
if (content) { if (content) {
console.log("initial md", content);
// Whenever the current Markdown content changes, converts it to an array // Whenever the current Markdown content changes, converts it to an array
// of Block objects and replaces the editor's content with them. // of Block objects and replaces the editor's content with them.
const getBlocks = async () => { const getBlocks = async () => {
const blocks: Block[] = await editor.markdownToBlocks(content); const blocks: Block[] = await editor.markdownToBlocks(content);
console.log("Blocks", blocks);
editor.replaceBlocks(editor.topLevelBlocks, blocks); editor.replaceBlocks(editor.topLevelBlocks, blocks);
setLoading(false); setLoading(false);
}; };
@ -41,7 +38,7 @@ export default function Markdown({ content }: MarkdoneProps) {
if (loading) { if (loading) {
return ( return (
<div className=""> <div className="center py-20 text-primary">
<Spinner /> <Spinner />
</div> </div>
); );

View File

@ -1,11 +1,11 @@
export const EXPLORE_CREATORS = [ export const EXPLORE_CREATORS = [
"npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s", "npub1xtscya34g58tk0z605fvr788k263gsu6cy9x0mhnm87echrgufzsevkk5s",
"npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
"npub1u6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8sus3tnd7t", "npub1u6qhg5ucu3xza4nlz94q90y720tr6l09avnq8y3yfp5qrv9v8sus3tnd7t",
"npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m", "npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m",
"npub19mduaf5569jx9xz555jcx3v06mvktvtpu0zgk47n4lcpjsz43zzqhj6vzk", "npub19mduaf5569jx9xz555jcx3v06mvktvtpu0zgk47n4lcpjsz43zzqhj6vzk",
"npub1dc9p7jzjhj86g2uqgltq4qvnpkyfqn9r72kdlddcgyat3j05gnjsgjc8rz", "npub1dc9p7jzjhj86g2uqgltq4qvnpkyfqn9r72kdlddcgyat3j05gnjsgjc8rz",
"npub1qny3tkh0acurzla8x3zy4nhrjz5zd8l9sy9jys09umwng00manysew95gx", "npub1qny3tkh0acurzla8x3zy4nhrjz5zd8l9sy9jys09umwng00manysew95gx",
"npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft",
]; ];
export const BANNER = export const BANNER =

View File

@ -1,7 +1,7 @@
export const RELAYS = [ export const RELAYS = [
"wss://nostr.pub.wellorder.net", "wss://nostr.mom",
"wss://nostr.drss.io", "wss://nos.lol",
"wss://nostr.swiss-enigma.ch",
"wss://relay.damus.io",
"wss://nostr.wine", "wss://nostr.wine",
"wss://relay.damus.io",
"wss://nostr.swiss-enigma.ch",
]; ];

View File

@ -7,56 +7,46 @@ import { Avatar, AvatarImage, AvatarFallback } from "@radix-ui/react-avatar";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { formatDate } from "@/lib/utils/dates"; import { formatDate } from "@/lib/utils/dates";
import Actions from "./Actions"; import Actions from "./Actions";
import Logo from "@/assets/Logo"; import { NDKEvent } from "@nostr-dev-kit/ndk";
import { getTagAllValues, getTagValues } from "@/lib/nostr/utils";
import useProfile from "@/lib/hooks/useProfile";
import { nip19 } from "nostr-tools";
import { getNameToShow, getTwoLetters } from "@/lib/utils";
export default function ArticlePage() { type ArticleProps = {
event: NDKEvent;
};
export default function ArticlePage({ event }: ArticleProps) {
const Viewer = useMemo( const Viewer = useMemo(
() => dynamic(() => import("@/components/LongForm"), { ssr: false }), () => dynamic(() => import("@/components/LongForm"), { ssr: false }),
[], [],
); );
console.log(event);
const router = useRouter(); const router = useRouter();
const markdown = `Do you have any thoughts of YakiHonne? Share it and earn SATs! const markdown = event.content;
const pubkey = event.pubkey;
Comment2Earn | Earn SATs by sharing your comments on YakiHonne const createdAt = getTagValues("published_at", event.tags)
? parseInt(getTagValues("published_at", event.tags) as string)
Earn SATs by sharing your comments on YakiHonne. : event.created_at;
const { profile } = useProfile(pubkey);
2nd - 15th Oct const npub = nip19.npubEncode(pubkey);
const title = getTagValues("title", event.tags);
### Follow Us const summary = getTagValues("summary", event.tags);
const tags = getTagAllValues("t", event.tags);
- Nostr: npub1yzvxlwp7wawed5vgefwfmugvumtp8c8t0etk3g8sky4n0ndvyxesnxrf8q
- Twitter: https://twitter.com/YakiHonne
- Facebook Profile: https://www.facebook.com/profi…1715056704
- Facebook Page: https://www.facebook.com/profi…2076811240
- Facebook Group: https://www.facebook.com/group…4539860115
- Youtube: https://www.youtube.com/channe…f4EyFJ7BlA
### How to Get SATs:
1. Post your thoughts about YakiHonne on at least one of the above social media, and be sure to @ YakiHonne.
2. Follow YakiHonne on at least one of the social media above.
3. Back to this article, leave your social account which followed YakiHonne in the Comments.
4. Be zapped with SATs.
### What You Will Get:
1. 500 SATs, if you finished all steps.
2. 1000 SATs, if you finished all steps and`;
return ( return (
<div className="relative @container"> <div className="relative @container">
<div className="sticky inset-x-0 top-0 z-10 flex items-center justify-between border-b bg-background pb-4 pt-4"> <div className="sticky inset-x-0 top-0 z-10 flex items-center justify-between border-b bg-background pb-4 pt-4">
<div className="center gap-x-3"> <div className="center gap-x-3">
<Avatar className="center h-8 w-8 overflow-hidden rounded-sm bg-muted"> <Avatar className="center h-8 w-8 overflow-hidden rounded-sm bg-muted">
<AvatarImage <AvatarImage src={profile?.image} alt="user" />
src={ <AvatarFallback className="text-xs">
"https://images.unsplash.com/photo-1566492031773-4f4e44671857?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=4&w=256&h=256&q=60" {getTwoLetters({ profile, npub })}
} </AvatarFallback>
alt="user"
/>
<AvatarFallback className="text-xs">SC</AvatarFallback>
</Avatar> </Avatar>
<span className="text-xs uppercase text-muted-foreground"> <span className="text-xs uppercase text-muted-foreground">
Derek Seivers {getNameToShow({ profile, npub })}
</span> </span>
</div> </div>
<Button <Button
@ -79,27 +69,27 @@ export default function ArticlePage() {
<article className="prose dark:prose-invert prose-zinc relative mx-auto max-w-3xl pt-7"> <article className="prose dark:prose-invert prose-zinc relative mx-auto max-w-3xl pt-7">
<div className=""> <div className="">
<div className="flex items-center justify-between gap-1 lg:mb-2"> <div className="flex items-center justify-between gap-1 lg:mb-2">
{tags.map((t) => (
<Button variant={"link"} className="px-0"> <Button variant={"link"} className="px-0">
Balaji's News Letter {t}
</Button> </Button>
))}
<div className="center text-xs text-muted-foreground/50"> <div className="center text-xs text-muted-foreground/50">
{!!createdAt && (
<span className="mr-2.5"> <span className="mr-2.5">
{formatDate(new Date("10-2-22"), "MMMM Do, YYYY")} {formatDate(new Date(createdAt * 1000), "MMMM Do, YYYY")}
</span> </span>
)}
<span className="h-3 w-[1px] rounded-full bg-muted-foreground/50"></span> <span className="h-3 w-[1px] rounded-full bg-muted-foreground/50"></span>
</div> </div>
</div> </div>
<h1 className=""> <h1 className="">{title}</h1>
This is the large title for the article. It's time to take over.
</h1>
<div className="mb-3 flex items-center justify-end"> <div className="mb-3 flex items-center justify-end">
<Actions /> <Actions />
</div> </div>
<div className="rounded-r-lg border-l-[4px] border-primary bg-muted p-4"> <div className="rounded-r-lg border-l-[4px] border-primary bg-muted p-4">
<p className="m-0"> <p className="m-0">{summary} </p>
Here is a short summary for the article that you are about to
start reading. Get ready to really enojy your self.
</p>
</div> </div>
</div> </div>
<Viewer content={markdown} /> <Viewer content={markdown} />