From 98132cee7e4c427cab4cec2af45e1b8102c59c3b Mon Sep 17 00:00:00 2001
From: crupest <crupest@outlook.com>
Date: Wed, 11 Nov 2020 21:02:15 +0800
Subject: refactor: Refactor timeline props.

---
 .../views/timeline-common/TimelinePageTemplate.tsx | 153 +++++++++++++--------
 1 file changed, 95 insertions(+), 58 deletions(-)

(limited to 'FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx')

diff --git a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
index 0f792b53..6c57e91d 100644
--- a/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
+++ b/FrontEnd/src/app/views/timeline-common/TimelinePageTemplate.tsx
@@ -12,11 +12,12 @@ import {
   useTimelineInfo,
 } from "@/services/timeline";
 
-import { TimelineDeleteCallback } from "./Timeline";
 import { TimelineMemberDialog } from "./TimelineMember";
 import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog";
 import { TimelinePageTemplateUIProps } from "./TimelinePageTemplateUI";
 import { TimelinePostSendCallback } from "./TimelinePostEdit";
+import { TimelineSyncStatus } from "./SyncStatusBadge";
+import { TimelinePostInfoEx } from "./Timeline";
 
 export interface TimelinePageTemplateProps<TManageItem> {
   name: string;
@@ -43,19 +44,101 @@ export default function TimelinePageTemplate<TManageItem>(
   );
 
   const timelineState = useTimelineInfo(name);
+  const postListState = usePostList(name);
 
-  const timeline = timelineState?.timeline;
+  const onPost: TimelinePostSendCallback = React.useCallback(
+    (req) => {
+      return service.createPost(name, req).toPromise().then();
+    },
+    [service, name]
+  );
 
-  const postListState = usePostList(name);
+  const onManageProp = props.onManage;
 
-  const error: string | undefined = (() => {
-    if (timelineState != null) {
+  const onManage = React.useCallback(
+    (item: "property" | TManageItem) => {
+      if (item === "property") {
+        setDialog(item);
+      } else {
+        onManageProp(item);
+      }
+    },
+    [onManageProp]
+  );
+
+  const childProps = ((): [
+    data: TimelinePageTemplateUIProps<TManageItem>["data"],
+    syncStatus: TimelineSyncStatus
+  ] => {
+    if (timelineState == null) {
+      return [undefined, "syncing"];
+    } else {
       const { type, timeline } = timelineState;
-      if (type === "offline" && timeline == null) return "Network Error";
-      if (type === "synced" && timeline == null)
-        return t(props.notFoundI18nKey);
+      if (timeline == null) {
+        if (type === "offline") {
+          return [{ type: "custom", value: "Network Error" }, "offline"];
+        } else if (type === "synced") {
+          return [props.notFoundI18nKey, "synced"];
+        } else {
+          return [undefined, "syncing"];
+        }
+      } else {
+        if (postListState != null && postListState.type === "notexist") {
+          return [props.notFoundI18nKey, "synced"];
+        }
+        if (postListState != null && postListState.type === "forbid") {
+          return ["timeline.messageCantSee", "synced"];
+        }
+
+        const posts:
+          | TimelinePostInfoEx[]
+          | undefined = postListState?.posts?.map((post) => ({
+          ...post,
+          onDelete: service.hasModifyPostPermission(user, timeline, post)
+            ? () => {
+                service.deletePost(name, post.id).subscribe({
+                  error: () => {
+                    pushAlert({
+                      type: "danger",
+                      message: t("timeline.deletePostFailed"),
+                    });
+                  },
+                });
+              }
+            : undefined,
+        }));
+
+        const others = {
+          onPost: service.hasPostPermission(user, timeline)
+            ? onPost
+            : undefined,
+          onManage: service.hasManagePermission(user, timeline)
+            ? onManage
+            : undefined,
+          onMember: () => setDialog("member"),
+        };
+
+        if (type === "cache") {
+          return [{ timeline, posts, ...others }, "syncing"];
+        } else if (type === "offline") {
+          return [{ timeline, posts, ...others }, "offline"];
+        } else {
+          if (postListState == null) {
+            return [{ timeline, posts, ...others }, "syncing"];
+          } else {
+            const { type: postListType } = postListState;
+            if (postListType === "synced") {
+              return [{ timeline, posts, ...others }, "synced"];
+            } else if (postListType === "cache") {
+              return [{ timeline, posts, ...others }, "syncing"];
+            } else if (postListType === "offline") {
+              return [{ timeline, posts, ...others }, "offline"];
+            }
+          }
+        }
+      }
     }
-    return undefined;
+    throw new UiLogicError("Failed to calculate TimelinePageUITemplate props.");
   })();
 
   const closeDialog = React.useCallback((): void => {
@@ -64,6 +147,8 @@ export default function TimelinePageTemplate<TManageItem>(
 
   let dialogElement: React.ReactElement | undefined;
 
+  const timeline = timelineState?.timeline;
+
   if (dialog === "property") {
     if (timeline == null) {
       throw new UiLogicError(
@@ -129,57 +214,9 @@ export default function TimelinePageTemplate<TManageItem>(
 
   const { UiComponent } = props;
 
-  const onDelete: TimelineDeleteCallback = React.useCallback(
-    (index, id) => {
-      service.deletePost(name, id).subscribe(null, () => {
-        pushAlert({
-          type: "danger",
-          message: t("timeline.deletePostFailed"),
-        });
-      });
-    },
-    [service, name, t]
-  );
-
-  const onPost: TimelinePostSendCallback = React.useCallback(
-    (req) => {
-      return service.createPost(name, req).toPromise().then();
-    },
-    [service, name]
-  );
-
-  const onManageProp = props.onManage;
-
-  const onManage = React.useCallback(
-    (item: "property" | TManageItem) => {
-      if (item === "property") {
-        setDialog(item);
-      } else {
-        onManageProp(item);
-      }
-    },
-    [onManageProp]
-  );
-
   return (
     <>
-      <UiComponent
-        error={error}
-        timeline={timeline ?? undefined}
-        postListState={postListState}
-        onDelete={onDelete}
-        onPost={
-          timeline != null && service.hasPostPermission(user, timeline)
-            ? onPost
-            : undefined
-        }
-        onManage={
-          timeline != null && service.hasManagePermission(user, timeline)
-            ? onManage
-            : undefined
-        }
-        onMember={() => setDialog("member")}
-      />
+      <UiComponent data={childProps[0]} syncStatus={childProps[1]} />
       {dialogElement}
     </>
   );
-- 
cgit v1.2.3

