move loadMore button to TimelineRenderer
continuous-integration/drone/push Build is running Details

This commit is contained in:
Martti Malmi 2024-02-02 12:17:14 +02:00
parent 3fa4dbf100
commit f3272bed57
14 changed files with 71 additions and 96 deletions

View File

@ -0,0 +1,35 @@
import { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import { FormattedMessage } from "react-intl";
interface ShowMoreProps {
text?: string;
className?: string;
onClick: () => void;
}
const LoadMore = ({ text, onClick, className = "" }: ShowMoreProps) => {
return (
<button type="button" className={className} onClick={onClick}>
{text || <FormattedMessage defaultMessage="Load more" id="00LcfG" />}
</button>
);
};
export default LoadMore;
export function AutoLoadMore({ text, onClick, className }: ShowMoreProps) {
const { ref, inView } = useInView({ rootMargin: "2000px" });
useEffect(() => {
if (inView) {
onClick();
}
}, [inView]);
return (
<div ref={ref}>
<LoadMore onClick={onClick} text={text} className={className} />
</div>
);
}

View File

@ -1,38 +0,0 @@
import classNames from "classnames";
import { useEffect } from "react";
import { useInView } from "react-intersection-observer";
import { FormattedMessage } from "react-intl";
interface ShowMoreProps {
text?: string;
className?: string;
onClick: () => void;
}
const ShowMore = ({ text, onClick, className = "" }: ShowMoreProps) => {
return (
<div className="show-more-container">
<button type="button" className={classNames("show-more", className)} onClick={onClick}>
{text || <FormattedMessage defaultMessage="Show More" id="O8Z8t9" />}
</button>
</div>
);
};
export default ShowMore;
export function AutoShowMore({ text, onClick, className }: ShowMoreProps) {
const { ref, inView } = useInView({ rootMargin: "2000px" });
useEffect(() => {
if (inView) {
onClick();
}
}, [inView]);
return (
<div ref={ref}>
<ShowMore onClick={onClick} text={text} className={className} />
</div>
);
}

View File

@ -31,16 +31,6 @@
border-radius: 0;
}
.thread-container .show-more {
background: var(--gray-superdark);
padding-left: 76px;
width: 100%;
text-align: left;
border-radius: 0;
padding-top: 10px;
padding-bottom: 10px;
}
.subthread-container {
position: relative;
}

View File

@ -2,7 +2,6 @@ import "./Timeline.css";
import { socialGraphInstance, TaggedNostrEvent } from "@snort/system";
import { useCallback, useMemo, useState } from "react";
import { FormattedMessage } from "react-intl";
import { DisplayAs, DisplayAsSelector } from "@/Components/Feed/DisplayAsSelector";
import { TimelineRenderer } from "@/Components/Feed/TimelineRenderer";
@ -18,7 +17,6 @@ export interface TimelineProps {
ignoreModeration?: boolean;
window?: number;
now?: number;
loadMore?: boolean;
noSort?: boolean;
displayAs?: DisplayAs;
showDisplayAsSelector?: boolean;
@ -91,14 +89,8 @@ const Timeline = (props: TimelineProps) => {
latest={latestAuthors}
showLatest={t => onShowLatest(t)}
displayAs={displayAs}
loadMore={() => feed.loadMore()}
/>
{(props.loadMore === undefined || props.loadMore === true) && (
<div className="flex items-center px-3 py-4">
<button type="button" onClick={() => feed.loadMore()}>
<FormattedMessage defaultMessage="Load more" id="00LcfG" />
</button>
</div>
)}
</>
);
};

View File

@ -4,7 +4,6 @@ import { EventKind, NostrEvent, TaggedNostrEvent } from "@snort/system";
import { ReactNode, useCallback, useMemo, useState } from "react";
import { Link } from "react-router-dom";
import { AutoShowMore } from "@/Components/Event/ShowMore";
import { DisplayAs, DisplayAsSelector } from "@/Components/Feed/DisplayAsSelector";
import { TimelineRenderer } from "@/Components/Feed/TimelineRenderer";
import useTimelineFeed, { TimelineFeedOptions, TimelineSubject } from "@/Feed/TimelineFeed";
@ -98,15 +97,8 @@ const TimelineFollows = (props: TimelineFollowsProps) => {
}
}}
displayAs={displayAs}
loadMore={() => feed.loadMore()}
/>
{mainFeed.length > 0 && (
<AutoShowMore
onClick={() => {
feed.loadMore();
}}
className="mx-3 my-4"
/>
)}
</>
);
};

View File

@ -4,6 +4,7 @@ import { useInView } from "react-intersection-observer";
import { FormattedMessage } from "react-intl";
import ErrorBoundary from "@/Components/ErrorBoundary";
import { AutoLoadMore } from "@/Components/Event/LoadMore";
import { DisplayAs } from "@/Components/Feed/DisplayAsSelector";
import ImageGridItem from "@/Components/Feed/ImageGridItem";
import { TimelineFragment } from "@/Components/Feed/TimelineFragment";
@ -23,6 +24,7 @@ export interface TimelineRendererProps {
noteOnClick?: (ev: TaggedNostrEvent) => void;
noteContext?: (ev: TaggedNostrEvent) => ReactNode;
displayAs?: DisplayAs;
loadMore?: () => void;
}
// filter frags[0].events that have media
@ -151,6 +153,7 @@ export function TimelineRenderer(props: TimelineRendererProps) {
</>
)}
{props.displayAs === "grid" ? <Grid frags={props.frags} /> : renderNotes()}
{props.loadMore && <AutoLoadMore className="mx-3 my-4" onClick={props.loadMore} />}
</div>
);
}

View File

@ -0,0 +1,26 @@
import { useEffect, useRef, useState } from "react";
export default function usePageDimensions() {
const ref = useRef<HTMLDivElement | null>(document.querySelector("#root"));
const [dimensions, setDimensions] = useState({
width: ref.current?.clientWidth ?? 0,
height: ref.current?.clientHeight ?? 0,
});
useEffect(() => {
if (ref.current && "ResizeObserver" in window) {
const observer = new ResizeObserver(entries => {
if (entries[0].target === ref.current) {
const { width, height } = entries[0].contentRect;
setDimensions({ width, height });
}
});
observer.observe(ref.current);
return () => observer.disconnect();
}
}, [ref]);
return dimensions;
}

View File

@ -1,20 +0,0 @@
import { useEffect, useRef, useState } from "react";
export default function usePageWidth() {
const ref = useRef<HTMLDivElement | null>(document.querySelector("#root"));
const [width, setWidth] = useState(0);
useEffect(() => {
const updateSize = () => {
if (ref.current) {
setWidth(ref.current.offsetWidth);
}
};
window.addEventListener("resize", updateSize);
updateSize();
return () => window.removeEventListener("resize", updateSize);
}, [ref]);
return width;
}

View File

@ -8,7 +8,7 @@ import NoteTime from "@/Components/Event/Note/NoteTime";
import NoteToSelf from "@/Components/User/NoteToSelf";
import ProfileImage from "@/Components/User/ProfileImage";
import useLogin from "@/Hooks/useLogin";
import usePageWidth from "@/Hooks/usePageWidth";
import usePageDimensions from "@/Hooks/usePageDimensions";
import { ChatParticipantProfile } from "@/Pages/Messages/ChatParticipant";
import DmWindow from "@/Pages/Messages/DmWindow";
import NewChatWindow from "@/Pages/Messages/NewChatWindow";
@ -21,7 +21,7 @@ export default function MessagesPage() {
const { formatMessage } = useIntl();
const navigate = useNavigate();
const { id } = useParams();
const pageWidth = usePageWidth();
const { width: pageWidth } = usePageDimensions();
const chats = useChatSystems();

View File

@ -4,7 +4,7 @@ import { unwrap } from "@snort/shared";
import { NostrEvent, NostrLink, TaggedNostrEvent } from "@snort/system";
import { lazy, Suspense, useEffect, useMemo } from "react";
import { AutoShowMore } from "@/Components/Event/ShowMore";
import { AutoLoadMore } from "@/Components/Event/LoadMore";
import PageSpinner from "@/Components/PageSpinner";
import { useNotificationsView } from "@/Feed/WorkerRelayView";
import useLogin from "@/Hooks/useLogin";
@ -63,7 +63,7 @@ export default function NotificationsPage({ onClick }: { onClick?: (link: NostrL
{login.publicKey &&
[...timeGrouped.entries()].map(([k, g]) => <NotificationGroup key={k} evs={g} onClick={onClick} />)}
<AutoShowMore onClick={() => {}} />
<AutoLoadMore onClick={() => {}} />
</div>
</>
);

View File

@ -77,7 +77,6 @@ export function ProfileNotesTab({ id, relays, isMe }: { id: HexKey; relays?: Arr
subject={subject}
postsOnly={false}
method={"LIMIT_UNTIL"}
loadMore={true}
ignoreModeration={true}
window={60 * 60 * 6}
/>

View File

@ -14,5 +14,5 @@ export function TopicsPage() {
[tags, pubKey],
);
return <Timeline subject={subject} postsOnly={true} method="TIME_RANGE" loadMore={true} window={60 * 60 * 6} />;
return <Timeline subject={subject} postsOnly={true} method="TIME_RANGE" showLoadMore={true} window={60 * 60 * 6} />;
}

View File

@ -773,9 +773,6 @@
"O3Jz4E": {
"defaultMessage": "Use your invite code to earn sats!"
},
"O8Z8t9": {
"defaultMessage": "Show More"
},
"OEW7yJ": {
"defaultMessage": "Zaps"
},

View File

@ -255,7 +255,6 @@
"NepkXH": "Can't vote with {amount} sats, please set a different default zap amount",
"NndBJE": "New users page",
"O3Jz4E": "Use your invite code to earn sats!",
"O8Z8t9": "Show More",
"OEW7yJ": "Zaps",
"OKhRC6": "Share",
"OLEm6z": "Unknown login error",