From 2c1f4538be13c42c9e4d5c8a8944b16b242292b1 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 6 Oct 2023 09:08:55 -0400 Subject: [PATCH] Adding cursor pagination. Fixes #2155 (#2173) * Adding cursor pagination. Fixes #2155 * Addressing PR comments. --------- Co-authored-by: SleeplessOne1917 --- src/server/index.tsx | 21 +++-- .../components/common/paginator-cursor.tsx | 46 +++++++++++ src/shared/components/community/community.tsx | 70 ++++++++--------- src/shared/components/home/home.tsx | 77 +++++++++++-------- 4 files changed, 138 insertions(+), 76 deletions(-) create mode 100644 src/shared/components/common/paginator-cursor.tsx diff --git a/src/server/index.tsx b/src/server/index.tsx index e0427fae..1f47177b 100644 --- a/src/server/index.tsx +++ b/src/server/index.tsx @@ -20,21 +20,26 @@ const [hostname, port] = process.env["LEMMY_UI_HOST"] server.use(express.json()); server.use(express.urlencoded({ extended: false })); -server.use( - getStaticDir(), - express.static(path.resolve("./dist"), { - maxAge: 24 * 60 * 60 * 1000, // 1 day - immutable: true, - }), -); -server.use(setCacheControl); + +const serverPath = path.resolve("./dist"); if ( !process.env["LEMMY_UI_DISABLE_CSP"] && !process.env["LEMMY_UI_DEBUG"] && process.env["NODE_ENV"] !== "development" ) { + server.use( + getStaticDir(), + express.static(serverPath, { + maxAge: 24 * 60 * 60 * 1000, // 1 day + immutable: true, + }), + ); server.use(setDefaultCsp); + server.use(setCacheControl); +} else { + // In debug mode, don't use the maxAge and immutable, or it breaks live reload for dev + server.use(getStaticDir(), express.static(serverPath)); } server.get("/.well-known/security.txt", SecurityHandler); diff --git a/src/shared/components/common/paginator-cursor.tsx b/src/shared/components/common/paginator-cursor.tsx new file mode 100644 index 00000000..46488b85 --- /dev/null +++ b/src/shared/components/common/paginator-cursor.tsx @@ -0,0 +1,46 @@ +import { Component, linkEvent } from "inferno"; +import { I18NextService } from "../../services"; +import { PaginationCursor } from "lemmy-js-client"; + +interface PaginatorCursorProps { + prevPage?: PaginationCursor; + nextPage?: PaginationCursor; + onNext(val: PaginationCursor): void; + onPrev(): void; +} + +function handlePrev(i: PaginatorCursor) { + i.props.onPrev(); +} + +function handleNext(i: PaginatorCursor) { + if (i.props.nextPage) { + i.props.onNext(i.props.nextPage); + } +} + +export class PaginatorCursor extends Component { + constructor(props: any, context: any) { + super(props, context); + } + render() { + return ( +
+ + +
+ ); + } +} diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index 59d32e8d..01ceb128 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -14,11 +14,7 @@ import { updateCommunityBlock, updatePersonBlock, } from "@utils/app"; -import { - getPageFromString, - getQueryParams, - getQueryString, -} from "@utils/helpers"; +import { getQueryParams, getQueryString } from "@utils/helpers"; import type { QueryParams } from "@utils/types"; import { RouteDataResponse } from "@utils/types"; import { Component, RefObject, createRef, linkEvent } from "inferno"; @@ -62,6 +58,7 @@ import { MarkCommentReplyAsRead, MarkPersonMentionAsRead, MarkPostAsRead, + PaginationCursor, PostResponse, PurgeComment, PurgeCommunity, @@ -96,12 +93,12 @@ import { BannerIconHeader } from "../common/banner-icon-header"; import { DataTypeSelect } from "../common/data-type-select"; import { HtmlTags } from "../common/html-tags"; import { Icon, Spinner } from "../common/icon"; -import { Paginator } from "../common/paginator"; import { SortSelect } from "../common/sort-select"; import { Sidebar } from "../community/sidebar"; import { SiteSidebar } from "../home/site-sidebar"; import { PostListings } from "../post/post-listings"; import { CommunityLink } from "./community-link"; +import { PaginatorCursor } from "../common/paginator-cursor"; type CommunityData = RouteDataResponse<{ communityRes: GetCommunityResponse; @@ -122,13 +119,13 @@ interface State { interface CommunityProps { dataType: DataType; sort: SortType; - page: number; + pageCursor?: PaginationCursor; } function getCommunityQueryParams() { return getQueryParams({ dataType: getDataTypeFromQuery, - page: getPageFromString, + pageCursor: cursor => cursor, sort: getSortTypeFromQuery, }); } @@ -165,7 +162,8 @@ export class Community extends Component< this.handleSortChange = this.handleSortChange.bind(this); this.handleDataTypeChange = this.handleDataTypeChange.bind(this); - this.handlePageChange = this.handlePageChange.bind(this); + this.handlePageNext = this.handlePageNext.bind(this); + this.handlePagePrev = this.handlePagePrev.bind(this); // All of the action binds this.handleDeleteCommunity = this.handleDeleteCommunity.bind(this); @@ -236,7 +234,7 @@ export class Community extends Component< static async fetchInitialData({ client, path, - query: { dataType: urlDataType, page: urlPage, sort: urlSort }, + query: { dataType: urlDataType, pageCursor, sort: urlSort }, }: InitialFetchRequest>): Promise< Promise > { @@ -251,15 +249,13 @@ export class Community extends Component< const sort = getSortTypeFromQuery(urlSort); - const page = getPageFromString(urlPage); - let postsResponse: RequestState = EMPTY_REQUEST; let commentsResponse: RequestState = EMPTY_REQUEST; if (dataType === DataType.Post) { const getPostsForm: GetPosts = { community_name: communityName, - page, + page_cursor: pageCursor, limit: fetchLimit, sort, type_: "All", @@ -270,7 +266,6 @@ export class Community extends Component< } else { const getCommentsForm: GetComments = { community_name: communityName, - page, limit: fetchLimit, sort: postToCommentSortType(sort), type_: "All", @@ -287,6 +282,12 @@ export class Community extends Component< }; } + get getNextPage(): PaginationCursor | undefined { + return this.state.postsRes.state === "success" + ? this.state.postsRes.data.next_page + : undefined; + } + get documentTitle(): string { const cRes = this.state.communityRes; return cRes.state === "success" @@ -295,6 +296,7 @@ export class Community extends Component< } renderCommunity() { + const { pageCursor } = getCommunityQueryParams(); switch (this.state.communityRes.state) { case "loading": return ( @@ -304,7 +306,6 @@ export class Community extends Component< ); case "success": { const res = this.state.communityRes.data; - const { page } = getCommunityQueryParams(); return ( <> @@ -341,13 +342,11 @@ export class Community extends Component< {this.selects(res)} {this.listings(res)} - this.state.postsRes.data.posts.length - } +