Skip to content

Commit

Permalink
feat: add pagination to feed
Browse files Browse the repository at this point in the history
  • Loading branch information
narol1024 committed May 26, 2024
1 parent 3e4a3d0 commit 836c69e
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 43 deletions.
21 changes: 17 additions & 4 deletions app/api/news/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,24 @@ import { NextResponse } from "next/server";

export async function GET(request: Request) {
try {
// Extract query parameters for pagination
const url = new URL(request.url);
const _pageNum = url.searchParams.get("pageNum");
const _pageSize = url.searchParams.get("pageSize");
if (!_pageNum || !_pageSize) {
throw new Error("pageNum and pageSize required");
}
const pageNum = parseInt(_pageNum, 10);
const pageSize = parseInt(_pageSize, 10);
const offset = pageNum * pageSize;

const { rows } = await sql`
SELECT users.username, news.id, users."avatarId", news.content, news.pictures, News."createdTime" AT TIME ZONE 'UTC' AS "createdTime"
FROM news
JOIN users ON News."ownerId" = users.Id
ORDER BY news."createdTime" DESC
SELECT users.username, news.id, users."avatarId", news.content, news.pictures, news."createdTime" AT TIME ZONE 'UTC' AS "createdTime", news.longitude, news.latitude
FROM news
JOIN users ON News."ownerId" = users.Id
ORDER BY news."createdTime" DESC
LIMIT ${pageSize}
OFFSET ${offset}
`;
if (rows.length > 0) {
return new NextResponse(
Expand Down
23 changes: 18 additions & 5 deletions app/home/Cobe/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { observer } from "mobx-react-lite";

export const Cobe = observer(() => {
const { news, location } = useStores();
const newsList = news.newsList;
const focusRef = useRef([-1, -1]);
const canvasRef = useRef<HTMLCanvasElement>(null);
const pointerInteracting = useRef<{ x: number; y: number } | null>(null);
Expand Down Expand Up @@ -43,6 +44,14 @@ export const Cobe = observer(() => {
canvasRef.current && (width = canvasRef.current.offsetWidth);
window.addEventListener("resize", onResize);
onResize();
console.log(
newsList.map((newsItem) => {
return {
location: [newsItem.longitude, newsItem.latitude],
size: 0.1,
};
})
);
const globe = createGlobe(canvasRef.current, {
devicePixelRatio: 2,
width: width * 2,
Expand All @@ -56,10 +65,12 @@ export const Cobe = observer(() => {
baseColor: [1, 1, 1],
markerColor: [251 / 255, 100 / 255, 21 / 255],
glowColor: [1.2, 1.2, 1.2],
markers: [
{ location: [37.7595, -122.4367], size: 0.03 },
{ location: [40.7128, -74.006], size: 0.1 },
],
markers: newsList.map((newsItem) => {
return {
location: [newsItem.latitude, newsItem.longitude],
size: 0.1,
};
}),
onRender: (state) => {
const isAutoRotation =
focusRef.current[0] === -1 && focusRef.current[1] === -1;
Expand Down Expand Up @@ -107,7 +118,8 @@ export const Cobe = observer(() => {
window.removeEventListener("resize", onResize);
};
}
}, []);
}, [newsList]);

useEffect(() => {
if (news.isPosting) {
const { longitude, latitude } = location;
Expand All @@ -116,6 +128,7 @@ export const Cobe = observer(() => {
focusRef.current = [-1, -1];
}
}, [news.isPosting]);

return (
<div
style={{
Expand Down
66 changes: 49 additions & 17 deletions app/home/News/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import React, { useEffect } from "react";
import React, { useCallback, useEffect, useRef, useState } from "react";
import {
Button,
Modal,
Expand All @@ -9,25 +9,43 @@ import {
ModalBody,
Spinner,
} from "@nextui-org/react";
import { NewsCard } from "../NewsCard";
import { observer } from "mobx-react-lite";
import { useStores } from "@/hooks/useStores";
import { NewsCard } from "../NewsCard";
import { Virtuoso } from "react-virtuoso";

export const News = observer(() => {
const { news } = useStores();
const [pageNum, setPageNum] = useState(0);
const hasLoadedFirstPageDataRef = useRef(false);
const newsList = news.newsList;

useEffect(() => {
const loadMore = useCallback(() => {
(async () => {
const res = await fetch("/api/news", {
cache: "no-store",
method: "GET",
});
const { result } = await res.json();
if (result && result.length) {
news.updateNewsList(result);
}
try {
const res = await fetch(`/api/news?pageNum=${pageNum}&pageSize=10`, {
cache: "no-store",
method: "GET",
});
const { result } = await res.json();
if (result && result.length) {
news.updateNewsList(result);
}
} catch (error) {}
})();
}, []);
}, [pageNum]);

useEffect(() => {
if (pageNum === 0) {
// 默认reactStrictMode为true,React会执行两次,这里用ref处理一下首页数据
if (hasLoadedFirstPageDataRef.current === false) {
loadMore();
hasLoadedFirstPageDataRef.current = true;
}
} else {
loadMore();
}
}, [pageNum]);

return (
<Modal
Expand All @@ -48,15 +66,29 @@ export const News = observer(() => {
<ModalHeader className="flex flex-col gap-1">
带着Mortal看世界
</ModalHeader>
{news.newsList.length === 0 ? (
{newsList.length === 0 ? (
<ModalBody className="min-h-64 py-4">
<Spinner />
</ModalBody>
) : (
<ModalBody className="block overflow-auto min-h-72 py-4 max-h-[60vh]">
{news.newsList.map((news) => {
return <NewsCard key={news.id} {...news} />;
})}
<ModalBody className="block overflow-auto min-h-72 py-4 max-h-[80vh]">
<Virtuoso
style={{ height: "560px" }}
totalCount={newsList.length}
endReached={() => {
setPageNum(pageNum + 1);
}}
itemContent={(index) => {
const newsItem = newsList[index];
return (
<NewsCard
key={newsItem.id}
isLast={index === newsList.length - 1}
{...newsItem}
/>
);
}}
/>
</ModalBody>
)}
</>
Expand Down
39 changes: 26 additions & 13 deletions app/home/NewsCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,18 @@ import timezone from "dayjs/plugin/timezone";
dayjs.extend(utc);
dayjs.extend(timezone);

export function NewsCard(props: NewsData) {
interface NewsCardProps extends NewsData {
isLast?: boolean;
}

export const NewsCard = React.memo(function NewsCard(props: NewsCardProps) {
const hasPicture = props.pictures.length > 0;
return (
<RawCard shadow="none" className="mb-8">
<CardHeader className="flex gap-3">
<RawCard
shadow="none"
className={`flex flex-col mb-8 ${hasPicture ? "h-[280px]" : "h-[180px]"}`}
>
<CardHeader className="flex flex-shrink-0 gap-3 h-[40px]">
<Image height={28} src={avatars[props.avatarId]} width={28} />
<div className="flex flex-col">
<p className="text-small">{props.username}</p>
Expand All @@ -29,18 +37,23 @@ export function NewsCard(props: NewsData) {
</p>
</div>
</CardHeader>
<CardBody>
<p className="mb-2">{props.content}</p>
<CardBody className="flex flex-1 flex-col">
<p className="flex-shrink-0 mb-2 text-sm line-clamp-3">
{props.content}
</p>
{props.pictures[0] && (
<Image
width={220}
height={110}
src={props.pictures[0]}
className="object-contain"
/>
<div className="flex-1 overflow-hidden">
<Image
src={props.pictures[0]}
className="object-cover h-full aspect-[16/9]"
classNames={{
wrapper: "h-full",
}}
/>
</div>
)}
</CardBody>
<Divider />
{!props.isLast && <Divider />}
</RawCard>
);
}
});
3 changes: 1 addition & 2 deletions app/stores/NewsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ export class NewsStore {
makeAutoObservable(this);
}
updateNewsList = (list: NewsData[]) => {
// TODO: 多页
this.newsList = [...list];
this.newsList = this.newsList.concat(list);
};
updateDraft = (draft: Partial<DraftData>) => {
this.draft = {
Expand Down
2 changes: 2 additions & 0 deletions app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export interface NewsData {
content: string;
pictures: string[];
createdTime: number;
longitude: number;
latitude: number;
}

export interface DraftData {
Expand Down
15 changes: 14 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"radash": "^12.1.0",
"react": "^18",
"react-dom": "^18",
"react-spring": "^9.7.3"
"react-spring": "^9.7.3",
"react-virtuoso": "^4.7.11"
},
"devDependencies": {
"@release-it/conventional-changelog": "^5.0.0",
Expand Down

0 comments on commit 836c69e

Please sign in to comment.