aboutsummaryrefslogtreecommitdiff
path: root/FrontEnd/src
diff options
context:
space:
mode:
Diffstat (limited to 'FrontEnd/src')
-rw-r--r--FrontEnd/src/app/views/timeline-common/Timeline.tsx77
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelineLoading.tsx18
-rw-r--r--FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx116
3 files changed, 105 insertions, 106 deletions
diff --git a/FrontEnd/src/app/views/timeline-common/Timeline.tsx b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
index 60fbc45c..72d38ffd 100644
--- a/FrontEnd/src/app/views/timeline-common/Timeline.tsx
+++ b/FrontEnd/src/app/views/timeline-common/Timeline.tsx
@@ -9,18 +9,18 @@ import { getHttpTimelineClient, HttpTimelinePostInfo } from "@/http/timeline";
import TimelinePagedPostListView from "./TimelinePagedPostListView";
import TimelineTop from "./TimelineTop";
+import TimelineLoading from "./TimelineLoading";
export interface TimelineProps {
className?: string;
style?: React.CSSProperties;
- timelineName: string;
+ timelineName?: string;
reloadKey: number;
onReload: () => void;
- onLoad?: () => void;
}
const Timeline: React.FC<TimelineProps> = (props) => {
- const { timelineName, className, style, reloadKey, onReload, onLoad } = props;
+ const { timelineName, className, style, reloadKey, onReload } = props;
const [state, setState] = React.useState<
"loading" | "loaded" | "offline" | "notexist" | "forbid" | "error"
@@ -33,56 +33,41 @@ const Timeline: React.FC<TimelineProps> = (props) => {
}, [timelineName]);
React.useEffect(() => {
- let subscribe = true;
+ if (timelineName != null) {
+ let subscribe = true;
- void getHttpTimelineClient()
- .listPost(timelineName)
- .then(
- (data) => {
- if (subscribe) {
- setState("loaded");
- setPosts(data);
+ void getHttpTimelineClient()
+ .listPost(timelineName)
+ .then(
+ (data) => {
+ if (subscribe) {
+ setState("loaded");
+ setPosts(data);
+ }
+ },
+ (error) => {
+ if (error instanceof HttpNetworkError) {
+ setState("offline");
+ } else if (error instanceof HttpForbiddenError) {
+ setState("forbid");
+ } else if (error instanceof HttpNotFoundError) {
+ setState("notexist");
+ } else {
+ console.error(error);
+ setState("error");
+ }
}
- },
- (error) => {
- if (error instanceof HttpNetworkError) {
- setState("offline");
- } else if (error instanceof HttpForbiddenError) {
- setState("forbid");
- } else if (error instanceof HttpNotFoundError) {
- setState("notexist");
- } else {
- console.error(error);
- setState("error");
- }
- }
- );
+ );
- return () => {
- subscribe = false;
- };
- }, [timelineName, reloadKey]);
-
- React.useEffect(() => {
- if (state === "loaded") {
- onLoad?.();
+ return () => {
+ subscribe = false;
+ };
}
- }, [state, onLoad]);
+ }, [timelineName, reloadKey]);
switch (state) {
case "loading":
- return (
- <>
- <TimelineTop
- className="timeline-top-loading-enter"
- height={100}
- lineProps={{
- center: "loading",
- startSegmentLength: 56,
- }}
- />
- </>
- );
+ return <TimelineLoading />;
case "offline":
return (
<div className={className} style={style}>
diff --git a/FrontEnd/src/app/views/timeline-common/TimelineLoading.tsx b/FrontEnd/src/app/views/timeline-common/TimelineLoading.tsx
new file mode 100644
index 00000000..fc42f4b4
--- /dev/null
+++ b/FrontEnd/src/app/views/timeline-common/TimelineLoading.tsx
@@ -0,0 +1,18 @@
+import React from "react";
+
+import TimelineTop from "./TimelineTop";
+
+const TimelineLoading: React.FC = () => {
+ return (
+ <TimelineTop
+ className="timeline-top-loading-enter"
+ height={100}
+ lineProps={{
+ center: "loading",
+ startSegmentLength: 56,
+ }}
+ />
+ );
+};
+
+export default TimelineLoading;
diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
index 5cde014b..5b6dfa9c 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
@@ -1,6 +1,6 @@
import React from "react";
import { useTranslation } from "react-i18next";
-import { Container, Spinner } from "react-bootstrap";
+import { Container } from "react-bootstrap";
import { HttpNetworkError, HttpNotFoundError } from "@/http/common";
import { getHttpTimelineClient, HttpTimelineInfo } from "@/http/timeline";
@@ -33,14 +33,16 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
const { t } = useTranslation();
- const [timeline, setTimeline] = React.useState<
- HttpTimelineInfo | "loading" | "offline" | "notexist" | "error"
+ const [state, setState] = React.useState<
+ "loading" | "done" | "offline" | "notexist" | "error"
>("loading");
+ const [timeline, setTimeline] = React.useState<HttpTimelineInfo | null>(null);
useReverseScrollPositionRemember();
React.useEffect(() => {
- setTimeline("loading");
+ setState("loading");
+ setTimeline(null);
}, [timelineName]);
React.useEffect(() => {
@@ -50,19 +52,21 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
.then(
(data) => {
if (subscribe) {
+ setState("done");
setTimeline(data);
}
},
(error) => {
if (subscribe) {
if (error instanceof HttpNetworkError) {
- setTimeline("offline");
+ setState("offline");
} else if (error instanceof HttpNotFoundError) {
- setTimeline("notexist");
+ setState("notexist");
} else {
console.error(error);
- setTimeline("error");
+ setState("error");
}
+ setTimeline(null);
}
}
);
@@ -71,10 +75,6 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
};
}, [timelineName, reloadKey]);
- const scrollToBottom = React.useCallback(() => {
- window.scrollTo(0, document.body.scrollHeight);
- }, []);
-
const [bottomSpaceHeight, setBottomSpaceHeight] = React.useState<number>(0);
const [timelineReloadKey, setTimelineReloadKey] = React.useState<number>(0);
@@ -116,25 +116,9 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
);
};
- let body: React.ReactElement;
-
- if (timeline == "loading") {
- body = (
- <div className="full-viewport-center-child">
- <Spinner variant="primary" animation="grow" />
- </div>
- );
- } else if (timeline === "offline") {
- // TODO: i18n
- body = <p className="text-danger">Offline!</p>;
- } else if (timeline === "notexist") {
- body = <p className="text-danger">{t(props.notFoundI18nKey)}</p>;
- } else if (timeline === "error") {
- // TODO: i18n
- body = <p className="text-danger">Error!</p>;
- } else {
- body = (
- <>
+ return (
+ <>
+ {timeline != null ? (
<CardComponent
className="timeline-template-card"
timeline={timeline}
@@ -142,37 +126,49 @@ const TimelinePageTemplate: React.FC<TimelinePageTemplateProps> = (props) => {
toggleCollapse={toggleCardCollapse}
onReload={onReload}
/>
- <Container
- className="px-0"
- style={{
- minHeight: `calc(100vh - ${56 + bottomSpaceHeight}px)`,
- }}
- >
- <Timeline
- timelineName={timeline.name}
- reloadKey={timelineReloadKey}
- onReload={reloadTimeline}
- onLoad={scrollToBottom}
+ ) : null}
+ <Container
+ className="px-0"
+ style={{
+ minHeight: `calc(100vh - ${56 + bottomSpaceHeight}px)`,
+ }}
+ >
+ {(() => {
+ if (state === "offline") {
+ // TODO: i18n
+ return <p className="text-danger">Offline!</p>;
+ } else if (state === "notexist") {
+ return <p className="text-danger">{t(props.notFoundI18nKey)}</p>;
+ } else if (state === "error") {
+ // TODO: i18n
+ return <p className="text-danger">Error!</p>;
+ } else {
+ return (
+ <Timeline
+ timelineName={timeline?.name}
+ reloadKey={timelineReloadKey}
+ onReload={reloadTimeline}
+ />
+ );
+ }
+ })()}
+ </Container>
+ {timeline != null && timeline.postable ? (
+ <>
+ <div
+ style={{ height: bottomSpaceHeight }}
+ className="flex-fix-length"
/>
- </Container>
- {timeline.postable ? (
- <>
- <div
- style={{ height: bottomSpaceHeight }}
- className="flex-fix-length"
- />
- <TimelinePostEdit
- className="fixed-bottom"
- timeline={timeline}
- onHeightChange={onPostEditHeightChange}
- onPosted={reloadTimeline}
- />
- </>
- ) : null}
- </>
- );
- }
- return body;
+ <TimelinePostEdit
+ className="fixed-bottom"
+ timeline={timeline}
+ onHeightChange={onPostEditHeightChange}
+ onPosted={reloadTimeline}
+ />
+ </>
+ ) : null}
+ </>
+ );
};
export default TimelinePageTemplate;