aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src/views/timeline/Timeline.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src/views/timeline/Timeline.tsx')
-rw-r--r--FrontEnd/src/views/timeline/Timeline.tsx128
1 files changed, 69 insertions, 59 deletions
diff --git a/FrontEnd/src/views/timeline/Timeline.tsx b/FrontEnd/src/views/timeline/Timeline.tsx
index 6399b6bc..84624313 100644
--- a/FrontEnd/src/views/timeline/Timeline.tsx
+++ b/FrontEnd/src/views/timeline/Timeline.tsx
@@ -1,5 +1,6 @@
import React from "react";
import classnames from "classnames";
+import { useScrollToBottom } from "@/utilities/hooks";
import { HubConnectionState } from "@microsoft/signalr";
import {
@@ -16,14 +17,14 @@ import {
import { useUser } from "@/services/user";
import { getTimelinePostUpdate$ } from "@/services/timeline";
-import TimelinePagedPostListView from "./TimelinePagedPostListView";
+import TimelinePostListView from "./TimelinePostListView";
import TimelineEmptyItem from "./TimelineEmptyItem";
import TimelineLoading from "./TimelineLoading";
import TimelinePostEdit from "./TimelinePostEdit";
import TimelinePostEditNoLogin from "./TimelinePostEditNoLogin";
import TimelineCard from "./TimelineCard";
-import "./index.css";
+import "./Timeline.css";
export interface TimelineProps {
className?: string;
@@ -46,6 +47,9 @@ const Timeline: React.FC<TimelineProps> = (props) => {
"offline" | "forbid" | "notfound" | "error" | null
>(null);
+ const [currentPage, setCurrentPage] = React.useState(1);
+ const [totalPage, setTotalPage] = React.useState(0);
+
const [timelineReloadKey, setTimelineReloadKey] = React.useState(0);
const [postsReloadKey, setPostsReloadKey] = React.useState(0);
@@ -60,71 +64,50 @@ const Timeline: React.FC<TimelineProps> = (props) => {
}, [timelineOwner, timelineName]);
React.useEffect(() => {
- if (timelineName != null) {
- let subscribe = true;
-
- getHttpTimelineClient()
- .getTimeline(timelineOwner, timelineName)
- .then(
- (t) => {
- if (subscribe) {
- setTimeline(t);
- }
- },
- (error) => {
- if (subscribe) {
- if (error instanceof HttpNetworkError) {
- setError("offline");
- } else if (error instanceof HttpForbiddenError) {
- setError("forbid");
- } else if (error instanceof HttpNotFoundError) {
- setError("notfound");
- } else {
- console.error(error);
- setError("error");
- }
- }
+ getHttpTimelineClient()
+ .getTimeline(timelineOwner, timelineName)
+ .then(
+ (t) => {
+ setTimeline(t);
+ },
+ (error) => {
+ if (error instanceof HttpNetworkError) {
+ setError("offline");
+ } else if (error instanceof HttpForbiddenError) {
+ setError("forbid");
+ } else if (error instanceof HttpNotFoundError) {
+ setError("notfound");
+ } else {
+ console.error(error);
+ setError("error");
}
- );
-
- return () => {
- subscribe = false;
- };
- }
+ }
+ );
}, [timelineOwner, timelineName, timelineReloadKey]);
React.useEffect(() => {
- let subscribe = true;
- void getHttpTimelineClient()
- .listPost(timelineOwner, timelineName)
+ getHttpTimelineClient()
+ .listPost(timelineOwner, timelineName, 1)
.then(
- (ps) => {
- if (subscribe) {
- setPosts(
- ps.items.filter(
- (p): p is HttpTimelinePostInfo => p.deleted === false
- )
- );
- }
+ (page) => {
+ setPosts(
+ page.items.filter((p): p is HttpTimelinePostInfo => !p.deleted)
+ );
+ setTotalPage(page.totalPageCount);
},
(error) => {
- if (subscribe) {
- if (error instanceof HttpNetworkError) {
- setError("offline");
- } else if (error instanceof HttpForbiddenError) {
- setError("forbid");
- } else if (error instanceof HttpNotFoundError) {
- setError("notfound");
- } else {
- console.error(error);
- setError("error");
- }
+ if (error instanceof HttpNetworkError) {
+ setError("offline");
+ } else if (error instanceof HttpForbiddenError) {
+ setError("forbid");
+ } else if (error instanceof HttpNotFoundError) {
+ setError("notfound");
+ } else {
+ console.error(error);
+ setError("error");
}
}
);
- return () => {
- subscribe = false;
- };
}, [timelineOwner, timelineName, postsReloadKey]);
React.useEffect(() => {
@@ -143,6 +126,33 @@ const Timeline: React.FC<TimelineProps> = (props) => {
};
}, [timelineOwner, timelineName]);
+ useScrollToBottom(() => {
+ console.log(`Load page ${currentPage + 1}.`);
+ setCurrentPage(currentPage + 1);
+ void getHttpTimelineClient()
+ .listPost(timelineOwner, timelineName, currentPage + 1)
+ .then(
+ (page) => {
+ const ps = page.items.filter(
+ (p): p is HttpTimelinePostInfo => !p.deleted
+ );
+ setPosts((old) => [...(old ?? []), ...ps]);
+ },
+ (error) => {
+ if (error instanceof HttpNetworkError) {
+ setError("offline");
+ } else if (error instanceof HttpForbiddenError) {
+ setError("forbid");
+ } else if (error instanceof HttpNotFoundError) {
+ setError("notfound");
+ } else {
+ console.error(error);
+ setError("error");
+ }
+ }
+ );
+ }, currentPage < totalPage);
+
if (error === "offline") {
return (
<div className={className} style={style}>
@@ -181,8 +191,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
)}
{posts && (
<div style={style} className={classnames("timeline", className)}>
- <TimelineEmptyItem height={40} />
- <TimelinePagedPostListView posts={posts} onReload={updatePosts} />
+ <TimelineEmptyItem height={50} />
{timeline?.postable ? (
<TimelinePostEdit timeline={timeline} onPosted={updatePosts} />
) : user == null ? (
@@ -190,6 +199,7 @@ const Timeline: React.FC<TimelineProps> = (props) => {
) : (
<TimelineEmptyItem startSegmentLength={20} center="none" current />
)}
+ <TimelinePostListView posts={posts} onReload={updatePosts} />
</div>
)}
</>