mirror of
https://github.com/lumehq/lume.git
synced 2025-04-10 04:49:11 +02:00
update threads (kind 30023) page
This commit is contained in:
parent
180e31d1bd
commit
7e8e5a931b
@ -1,8 +1,15 @@
|
||||
import { useProfile } from "@utils/hooks/useProfile";
|
||||
import { shortenKey } from "@utils/shortenKey";
|
||||
|
||||
const hexRegex = /[0-9A-Fa-f]{6}/g;
|
||||
|
||||
export function MentionUser(props: { children: any[] }) {
|
||||
const pubkey = props.children[0];
|
||||
const pubkey = props.children[0].match(hexRegex) ? props.children[0] : null;
|
||||
|
||||
if (!pubkey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { user } = useProfile(pubkey);
|
||||
|
||||
return (
|
||||
|
@ -1,11 +1,40 @@
|
||||
import { Image } from "@shared/image";
|
||||
import { DEFAULT_AVATAR, IMGPROXY_URL } from "@stores/constants";
|
||||
import { useProfile } from "@utils/hooks/useProfile";
|
||||
import { shortenKey } from "@utils/shortenKey";
|
||||
import dayjs from "dayjs";
|
||||
|
||||
export function ThreadAuthor({
|
||||
pubkey,
|
||||
time,
|
||||
}: { pubkey: string; time: number }) {
|
||||
const { user } = useProfile(pubkey);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>{pubkey}</p>
|
||||
<span>{time}</span>
|
||||
<div className="relative flex items-center gap-2.5">
|
||||
<div className="h-9 w-9 shrink-0 overflow-hidden rounded-md bg-zinc-900">
|
||||
<Image
|
||||
src={`${IMGPROXY_URL}/rs:fit:100:100/plain/${
|
||||
user?.picture ? user.picture : DEFAULT_AVATAR
|
||||
}`}
|
||||
alt={pubkey}
|
||||
className="h-9 w-9 object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex w-full flex-1 items-start justify-between">
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<h5 className="text-sm font-semibold leading-none">
|
||||
{user?.display_name || user?.name || (
|
||||
<div className="h-3 w-20 animate-pulse rounded-sm bg-zinc-700" />
|
||||
)}
|
||||
</h5>
|
||||
<div className="flex items-baseline gap-1.5 text-sm leading-none text-zinc-500">
|
||||
<span>{user?.nip05 || shortenKey(pubkey)}</span>
|
||||
<span>•</span>
|
||||
<span>{dayjs().to(dayjs.unix(time), true)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,18 +1,37 @@
|
||||
import { ThreadAuthor } from "@app/threads/components/author";
|
||||
import { Image } from "@shared/image";
|
||||
|
||||
export function ThreadBase({ event }: { event: any }) {
|
||||
const metadata = JSON.parse(event.metadata);
|
||||
const title = metadata.find((i: any) => i[0] === "title")[1];
|
||||
const summary = metadata.find((i: any) => i[0] === "summary")[1] || "";
|
||||
const metadata = JSON.parse(event.tags);
|
||||
const title = metadata.find((i: any) => i[0] === "title")?.[1];
|
||||
const summary = metadata.find((i: any) => i[0] === "summary")?.[1];
|
||||
const image = metadata.find((i: any) => i[0] === "image")?.[1];
|
||||
|
||||
if (!title) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-min w-full px-3 py-1.5">
|
||||
<div className="rounded-md border border-zinc-800 bg-zinc-900 shadow-input shadow-black/20">
|
||||
<div className="px-3 py-3">
|
||||
<h3>{title}</h3>
|
||||
<p>{summary}</p>
|
||||
<div className="flex flex-row gap-2">
|
||||
<div className="flex-1">
|
||||
<h3 className="text-zinc-100 text-xl font-semibold">{title}</h3>
|
||||
<div className="mt-2 prose prose-zinc max-w-none select-text break-words dark:prose-invert prose-p:text-[15px] prose-p:leading-tight prose-a:text-[15px] prose-a:font-normal prose-a:leading-tight prose-a:text-fuchsia-500 prose-a:no-underline hover:prose-a:text-fuchsia-600 hover:prose-a:underline prose-ol:mb-1 prose-ul:mb-1 prose-li:text-[15px] prose-li:leading-tight">
|
||||
<p>{summary}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="shrink-0 w-32 h-32">
|
||||
<Image
|
||||
src={image}
|
||||
alt={title}
|
||||
className="w-32 h-32 rounded-md object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="inline-flex w-full justify-between items-center px-3 h-10">
|
||||
<div className="inline-flex border-t border-zinc-800 w-full justify-between items-center px-3 h-16">
|
||||
<ThreadAuthor pubkey={event.pubkey} time={event.created_at} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -8,6 +8,15 @@ import { useEffect, useRef } from "react";
|
||||
const ITEM_PER_PAGE = 10;
|
||||
const TIME = Math.floor(Date.now() / 1000);
|
||||
|
||||
function isJSON(str: string) {
|
||||
try {
|
||||
JSON.parse(str);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function Page() {
|
||||
const {
|
||||
status,
|
||||
@ -56,7 +65,7 @@ export function Page() {
|
||||
return (
|
||||
<div
|
||||
ref={parentRef}
|
||||
className="scrollbar-hide flex h-full flex-col justify-between gap-1.5 overflow-y-auto"
|
||||
className="scrollbar-hide h-full overflow-y-auto"
|
||||
style={{ contain: "strict" }}
|
||||
>
|
||||
{status === "loading" ? (
|
||||
@ -69,7 +78,7 @@ export function Page() {
|
||||
<div>{error.message}</div>
|
||||
) : (
|
||||
<div
|
||||
className="relative w-full"
|
||||
className="relative w-full mt-2"
|
||||
style={{
|
||||
height: `${rowVirtualizer.getTotalSize()}px`,
|
||||
}}
|
||||
@ -84,7 +93,7 @@ export function Page() {
|
||||
>
|
||||
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
|
||||
const note = allRows[virtualRow.index];
|
||||
if (note) {
|
||||
if (note && isJSON(note.tags)) {
|
||||
return (
|
||||
<div
|
||||
key={virtualRow.index}
|
||||
|
Loading…
x
Reference in New Issue
Block a user