2023-05-10 11:32:09 +00:00
|
|
|
import { useEffect, useState } from "react";
|
2023-09-19 08:30:01 +00:00
|
|
|
import { NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/system";
|
2023-11-09 12:20:53 +00:00
|
|
|
import { useReactions } from "@snort/system-react";
|
2023-05-10 11:32:09 +00:00
|
|
|
|
2023-11-17 11:52:10 +00:00
|
|
|
import PageSpinner from "@/Element/PageSpinner";
|
|
|
|
import Note from "@/Element/Event/Note";
|
|
|
|
import NostrBandApi from "@/External/NostrBand";
|
|
|
|
import { ErrorOrOffline } from "@/Element/ErrorOrOffline";
|
|
|
|
import { useLocale } from "@/IntlProvider";
|
|
|
|
import useModeration from "@/Hooks/useModeration";
|
2023-11-30 10:52:13 +00:00
|
|
|
import ShortNote from "@/Element/Trending/ShortNote";
|
|
|
|
import classNames from "classnames";
|
2023-12-07 11:33:36 +00:00
|
|
|
import { DisplayAs, DisplayAsSelector } from "@/Element/Feed/DisplayAsSelector";
|
|
|
|
import ImageGridItem from "@/Element/Feed/ImageGridItem";
|
2023-12-07 11:56:03 +00:00
|
|
|
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
|
|
|
|
import useLogin from "@/Hooks/useLogin";
|
2023-05-10 11:32:09 +00:00
|
|
|
|
2023-11-25 19:19:22 +00:00
|
|
|
export default function TrendingNotes({ count = Infinity, small = false }) {
|
2023-12-07 11:56:03 +00:00
|
|
|
const login = useLogin();
|
|
|
|
const displayAsInitial = small ? "list" : login.feedDisplayAs ?? "list";
|
2023-11-22 12:06:42 +00:00
|
|
|
// Added count prop with a default value
|
2023-06-01 21:03:28 +00:00
|
|
|
const [posts, setPosts] = useState<Array<NostrEvent>>();
|
2023-10-31 15:40:12 +00:00
|
|
|
const [error, setError] = useState<Error>();
|
2023-11-10 09:54:08 +00:00
|
|
|
const { lang } = useLocale();
|
2023-11-17 11:28:11 +00:00
|
|
|
const { isEventMuted } = useModeration();
|
2023-12-07 11:56:03 +00:00
|
|
|
const [displayAs, setDisplayAs] = useState<DisplayAs>(displayAsInitial);
|
2023-11-09 12:20:53 +00:00
|
|
|
const related = useReactions("trending", posts?.map(a => NostrLink.fromEvent(a)) ?? [], undefined, true);
|
2023-12-07 11:56:03 +00:00
|
|
|
const [modalThread, setModalThread] = useState<NostrLink | undefined>(undefined);
|
2023-05-10 11:32:09 +00:00
|
|
|
|
|
|
|
async function loadTrendingNotes() {
|
|
|
|
const api = new NostrBandApi();
|
2023-11-10 09:54:08 +00:00
|
|
|
const trending = await api.trendingNotes(lang);
|
2023-05-10 11:32:09 +00:00
|
|
|
setPosts(trending.notes.map(a => a.event));
|
|
|
|
}
|
|
|
|
|
|
|
|
useEffect(() => {
|
2023-10-31 15:40:12 +00:00
|
|
|
loadTrendingNotes().catch(e => {
|
|
|
|
if (e instanceof Error) {
|
|
|
|
setError(e);
|
|
|
|
}
|
|
|
|
});
|
2023-05-10 11:32:09 +00:00
|
|
|
}, []);
|
|
|
|
|
2023-10-31 15:40:12 +00:00
|
|
|
if (error) return <ErrorOrOffline error={error} onRetry={loadTrendingNotes} className="p" />;
|
2023-05-10 11:32:09 +00:00
|
|
|
if (!posts) return <PageSpinner />;
|
|
|
|
|
2023-11-25 19:19:22 +00:00
|
|
|
// if small, render less stuff
|
|
|
|
const options = {
|
|
|
|
showFooter: !small,
|
|
|
|
showReactionsLink: !small,
|
|
|
|
showMedia: !small,
|
|
|
|
longFormPreview: !small,
|
|
|
|
truncate: small,
|
|
|
|
showContextMenu: !small,
|
|
|
|
};
|
|
|
|
|
2023-12-07 11:33:36 +00:00
|
|
|
const filteredAndLimitedPosts = () => {
|
|
|
|
return posts.filter(a => !isEventMuted(a)).slice(0, count);
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderGrid = () => {
|
|
|
|
return (
|
|
|
|
<div className="grid grid-cols-3 gap-px md:gap-1">
|
|
|
|
{filteredAndLimitedPosts().map(e => (
|
2023-12-21 20:05:00 +00:00
|
|
|
<ImageGridItem key={e.id} event={e as TaggedNostrEvent} onClick={() => setModalThread(NostrLink.fromEvent(e))} />
|
2023-12-07 11:33:36 +00:00
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const renderList = () => {
|
|
|
|
return filteredAndLimitedPosts().map(e =>
|
|
|
|
small ? (
|
2023-12-21 20:05:00 +00:00
|
|
|
<ShortNote key={e.id} event={e as TaggedNostrEvent} />
|
2023-12-07 11:33:36 +00:00
|
|
|
) : (
|
2023-12-21 20:05:00 +00:00
|
|
|
<Note key={e.id} data={e as TaggedNostrEvent} related={related?.data ?? []} depth={0} options={options} />
|
2023-12-07 11:33:36 +00:00
|
|
|
),
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2023-05-10 11:32:09 +00:00
|
|
|
return (
|
2023-11-30 11:14:29 +00:00
|
|
|
<div className={classNames("flex flex-col", { "gap-6": small, "py-4": small })}>
|
2023-12-07 11:33:36 +00:00
|
|
|
{!small && <DisplayAsSelector activeSelection={displayAs} onSelect={a => setDisplayAs(a)} />}
|
|
|
|
{displayAs === "grid" ? renderGrid() : renderList()}
|
2023-12-07 11:56:03 +00:00
|
|
|
{modalThread && (
|
|
|
|
<SpotlightThreadModal
|
|
|
|
thread={modalThread}
|
|
|
|
onClose={() => setModalThread(undefined)}
|
|
|
|
onBack={() => setModalThread(undefined)}
|
|
|
|
/>
|
|
|
|
)}
|
2023-11-25 19:19:22 +00:00
|
|
|
</div>
|
2023-05-10 11:32:09 +00:00
|
|
|
);
|
|
|
|
}
|