import React from "react"; import { UiLogicError } from "@/common"; import { useUser } from "@/services/user"; import { TimelinePostInfo, timelineService, usePosts, useTimeline, } from "@/services/timeline"; import { mergeDataStatus } from "@/services/DataHub2"; import { TimelineMemberDialog } from "./TimelineMember"; import TimelinePropertyChangeDialog from "./TimelinePropertyChangeDialog"; import { TimelinePageTemplateUIOperations, TimelinePageTemplateUIProps, } from "./TimelinePageTemplateUI"; export interface TimelinePageTemplateProps { name: string; onManage: (item: TManageItem) => void; UiComponent: React.ComponentType< Omit, "CardComponent"> >; notFoundI18nKey: string; } export default function TimelinePageTemplate( props: TimelinePageTemplateProps ): React.ReactElement | null { const { name } = props; const service = timelineService; const user = useUser(); const [dialog, setDialog] = React.useState( null ); const [scrollBottomKey, setScrollBottomKey] = React.useState(0); React.useEffect(() => { if (scrollBottomKey > 0) { window.scrollTo(0, document.body.scrollHeight); } }, [scrollBottomKey]); const timelineAndStatus = useTimeline(name); const postsAndState = usePosts(name); const [ scrollToBottomNextSyncKey, setScrollToBottomNextSyncKey, ] = React.useState(0); const scrollToBottomNextSync = (): void => { setScrollToBottomNextSyncKey((old) => old + 1); }; React.useEffect(() => { let subscribe = true; void timelineService.syncPosts(name).then(() => { if (subscribe) { setScrollBottomKey((old) => old + 1); } }); return () => { subscribe = false; }; }, [name, scrollToBottomNextSyncKey]); const uiTimelineProp = ((): TimelinePageTemplateUIProps["timeline"] => { const { status, data: timeline } = timelineAndStatus; if (timeline == null) { if (status === "offline") { return "offline"; } else { return undefined; } } else if (timeline === "notexist") { return "notexist"; } else { const operations: TimelinePageTemplateUIOperations = { onPost: service.hasPostPermission(user, timeline) ? (req) => service.createPost(name, req).then(() => scrollToBottomNextSync()) : undefined, onManage: service.hasManagePermission(user, timeline) ? (item) => { if (item === "property") { setDialog(item); } else { props.onManage(item); } } : undefined, onMember: () => setDialog("member"), }; const posts = ((): TimelinePostInfo[] | "forbid" | undefined => { const { data: postsInfo } = postsAndState; if (postsInfo === "forbid") { return "forbid"; } else if (postsInfo == null || postsInfo === "notexist") { return undefined; } else { return postsInfo.posts; } })(); return { ...timeline, operations, posts }; } })(); const timeline = timelineAndStatus?.data; let dialogElement: React.ReactElement | undefined; const closeDialog = (): void => setDialog(null); if (dialog === "property") { if (timeline == null || timeline === "notexist") { throw new UiLogicError( "Timeline is null but attempt to open change property dialog." ); } dialogElement = ( service.changeTimelineProperty(name, req)} /> ); } else if (dialog === "member") { if (timeline == null || timeline === "notexist") { throw new UiLogicError( "Timeline is null but attempt to open change property dialog." ); } dialogElement = ( ); } const { UiComponent } = props; return ( <> {dialogElement} ); }