diff --git a/packages/app/src/Element/Feed/ImageGridItem.tsx b/packages/app/src/Element/Feed/ImageGridItem.tsx
new file mode 100644
index 000000000..68e01e745
--- /dev/null
+++ b/packages/app/src/Element/Feed/ImageGridItem.tsx
@@ -0,0 +1,41 @@
+import { NostrLink, TaggedNostrEvent } from "@snort/system";
+import { MouseEvent } from "react";
+import useImgProxy from "@/Hooks/useImgProxy";
+import { transformTextCached } from "@/Hooks/useTextTransformCache";
+import { Link } from "react-router-dom";
+import Icon from "@/Icons/Icon";
+
+const ImageGridItem = (props: { event: TaggedNostrEvent; onClick: (e: MouseEvent) => void }) => {
+ const { event, onClick } = props;
+ const { proxy } = useImgProxy();
+
+ const parsed = transformTextCached(event.id, event.content, event.tags);
+ const media = parsed.filter(
+ a => a.type === "media" && (a.mimeType?.startsWith("image/") || a.mimeType?.startsWith("video/")),
+ );
+
+ if (media.length === 0) return null;
+
+ const multiple = media.length > 1;
+ const isVideo = media[0].mimeType?.startsWith("video/");
+ const noteId = NostrLink.fromEvent(event).encode(CONFIG.eventLinkPrefix);
+
+ const myOnClick = (clickEvent: MouseEvent) => {
+ if (onClick) {
+ onClick(clickEvent);
+ clickEvent.preventDefault();
+ }
+ };
+
+ return (
+
+
+
+ {multiple && }
+ {isVideo && }
+
+
+ );
+};
+
+export default ImageGridItem;
diff --git a/packages/app/src/Element/Feed/RootTabs.tsx b/packages/app/src/Element/Feed/RootTabs.tsx
index 4a4f7bd3c..20e24ec6d 100644
--- a/packages/app/src/Element/Feed/RootTabs.tsx
+++ b/packages/app/src/Element/Feed/RootTabs.tsx
@@ -142,7 +142,7 @@ export function RootTabs({ base = "/" }) {
if (currentTab && currentTab !== rootType) {
setRootType(currentTab);
}
- }, [location, menuItems, rootType]);
+ }, [location.pathname, menuItems, rootType]);
function currentMenuItem() {
if (location.pathname.startsWith(`${base}/t/`)) {
diff --git a/packages/app/src/Element/Feed/TimelineRenderer.tsx b/packages/app/src/Element/Feed/TimelineRenderer.tsx
index d6ef79601..a8edfe233 100644
--- a/packages/app/src/Element/Feed/TimelineRenderer.tsx
+++ b/packages/app/src/Element/Feed/TimelineRenderer.tsx
@@ -5,11 +5,9 @@ import Icon from "@/Icons/Icon";
import { NostrLink, TaggedNostrEvent } from "@snort/system";
import { ReactNode, useState } from "react";
import { TimelineFragment } from "@/Element/Feed/TimelineFragment";
-import { transformTextCached } from "@/Hooks/useTextTransformCache";
-import useImgProxy from "@/Hooks/useImgProxy";
-import { Link } from "react-router-dom";
import { DisplayAs } from "@/Element/Feed/DisplayAsSelector";
import { SpotlightThreadModal } from "@/Element/Spotlight/SpotlightThreadModal";
+import ImageGridItem from "@/Element/Feed/ImageGridItem";
export interface TimelineRendererProps {
frags: Array;
@@ -27,7 +25,6 @@ export interface TimelineRendererProps {
export function TimelineRenderer(props: TimelineRendererProps) {
const { ref, inView } = useInView();
- const { proxy } = useImgProxy();
const [modalThread, setModalThread] = useState(undefined);
const renderNotes = () => {
@@ -44,43 +41,13 @@ export function TimelineRenderer(props: TimelineRendererProps) {
const renderGrid = () => {
// TODO Hide images from notes with a content warning, unless otherwise configured
- const noteImageRenderer = (e: TaggedNostrEvent) => {
- const parsed = transformTextCached(e.id, e.content, e.tags);
- const media = parsed.filter(
- a => a.type === "media" && (a.mimeType?.startsWith("image/") || a.mimeType?.startsWith("video/")),
- );
-
- if (media.length === 0) return null;
-
- const multiple = media.length > 1;
- const isVideo = media[0].mimeType?.startsWith("video/");
- const noteId = NostrLink.fromEvent(e).encode(CONFIG.eventLinkPrefix);
-
- const onClick = (clickEvent: React.MouseEvent) => {
- if (props.noteOnClick) {
- props.noteOnClick(e);
- clickEvent.preventDefault();
- } else if (window.innerWidth >= 768) {
- setModalThread(NostrLink.fromEvent(e));
- clickEvent.preventDefault();
- }
- };
-
- return (
-
-
-
- {multiple && }
- {isVideo && }
-
-
- );
- };
-
- const noteRenderer = props.noteRenderer || noteImageRenderer;
return props.frags.map(frag => (
- {frag.events.map(event => noteRenderer(event))}
+
+ {frag.events.map(event => (
+ setModalThread(NostrLink.fromEvent(event))} />
+ ))}
+
));
};
diff --git a/packages/app/src/Element/Trending/TrendingPosts.tsx b/packages/app/src/Element/Trending/TrendingPosts.tsx
index 4213bffad..24468bbfb 100644
--- a/packages/app/src/Element/Trending/TrendingPosts.tsx
+++ b/packages/app/src/Element/Trending/TrendingPosts.tsx
@@ -10,6 +10,8 @@ import { useLocale } from "@/IntlProvider";
import useModeration from "@/Hooks/useModeration";
import ShortNote from "@/Element/Trending/ShortNote";
import classNames from "classnames";
+import { DisplayAs, DisplayAsSelector } from "@/Element/Feed/DisplayAsSelector";
+import ImageGridItem from "@/Element/Feed/ImageGridItem";
export default function TrendingNotes({ count = Infinity, small = false }) {
// Added count prop with a default value
@@ -17,6 +19,7 @@ export default function TrendingNotes({ count = Infinity, small = false }) {
const [error, setError] = useState();
const { lang } = useLocale();
const { isEventMuted } = useModeration();
+ const [displayAs, setDisplayAs] = useState("list");
const related = useReactions("trending", posts?.map(a => NostrLink.fromEvent(a)) ?? [], undefined, true);
async function loadTrendingNotes() {
@@ -46,18 +49,34 @@ export default function TrendingNotes({ count = Infinity, small = false }) {
showContextMenu: !small,
};
+ const filteredAndLimitedPosts = () => {
+ return posts.filter(a => !isEventMuted(a)).slice(0, count);
+ };
+
+ const renderGrid = () => {
+ return (
+
+ {filteredAndLimitedPosts().map(e => (
+ {}} />
+ ))}
+
+ );
+ };
+
+ const renderList = () => {
+ return filteredAndLimitedPosts().map(e =>
+ small ? (
+
+ ) : (
+
+ ),
+ );
+ };
+
return (
- {posts
- .filter(a => !isEventMuted(a))
- .slice(0, count) // Limit the number of posts displayed
- .map(e =>
- small ? (
-
- ) : (
-
- ),
- )}
+ {!small && setDisplayAs(a)} />}
+ {displayAs === "grid" ? renderGrid() : renderList()}
);
}