import React from 'react'; import { Spinner } from 'reactstrap'; import { useTranslation } from 'react-i18next'; import { Subject } from 'rxjs'; import { getAlertHost } from '../common/alert-service'; import Timeline, { TimelinePostInfoEx, TimelineDeleteCallback, } from './Timeline'; import AppBar from '../common/AppBar'; import TimelinePostEdit, { TimelinePostSendCallback } from './TimelinePostEdit'; import CollapseButton from '../common/CollapseButton'; export interface TimelineCardComponentProps { timeline: TTimeline; onManage?: (item: TManageItems | 'property') => void; onMember: () => void; className?: string; onHeight?: (height: number) => void; } export interface TimelinePageTemplateUIProps< TTimeline extends { name: string }, TManageItems > { avatarKey?: string | number; timeline?: TTimeline; posts?: TimelinePostInfoEx[] | 'forbid'; CardComponent: React.ComponentType< TimelineCardComponentProps >; onMember: () => void; onManage?: (item: TManageItems | 'property') => void; onPost?: TimelinePostSendCallback; onDelete: TimelineDeleteCallback; error?: string; } export default function TimelinePageTemplateUI< TTimeline extends { name: string }, TEditItems >( props: TimelinePageTemplateUIProps ): React.ReactElement | null { const { timeline } = props; const { t } = useTranslation(); const bottomSpaceRef = React.useRef(null); const onPostEditHeightChange = React.useCallback((height: number): void => { const { current: bottomSpaceDiv } = bottomSpaceRef; if (bottomSpaceDiv != null) { bottomSpaceDiv.style.height = `${height}px`; } if (height === 0) { const alertHost = getAlertHost(); if (alertHost != null) { alertHost.style.removeProperty('margin-bottom'); } } else { const alertHost = getAlertHost(); if (alertHost != null) { alertHost.style.marginBottom = `${height}px`; } } }, []); const onLoadSubject = React.useMemo(() => new Subject(), []); const triggerLoadEvent = React.useCallback(() => { onLoadSubject.next(null); }, [onLoadSubject]); React.useEffect(() => { let jumpToBottom = true; const timerTag = window.setTimeout(() => { jumpToBottom = false; }, 1000); const subscription = onLoadSubject.subscribe(() => { if (jumpToBottom) window.scrollTo(0, document.body.getBoundingClientRect().height); }); return () => { clearTimeout(timerTag); subscription.unsubscribe(); }; }, [onLoadSubject, timeline, props.posts]); const [cardHeight, setCardHeight] = React.useState(0); const onCardHeightChange = React.useCallback((height: number) => { setCardHeight(height); }, []); const genCardCollapseLocalStorageKey = (timelineName: string): string => `timeline.${timelineName}.cardCollapse`; const cardCollapseLocalStorageKey = timeline != null ? genCardCollapseLocalStorageKey(timeline.name) : null; const [infoCardCollapse, setInfoCardCollapse] = React.useState( false ); React.useEffect(() => { if (cardCollapseLocalStorageKey != null) { const savedCollapse = window.localStorage.getItem(cardCollapseLocalStorageKey) === 'true'; setInfoCardCollapse(savedCollapse); } }, [cardCollapseLocalStorageKey]); let body: React.ReactElement; if (props.error != null) { body =

{t(props.error)}

; } else { if (timeline != null) { let timelineBody: React.ReactElement; if (props.posts != null) { if (props.posts === 'forbid') { timelineBody = (

{t('timeline.messageCantSee')}

); } else { timelineBody = ( ); if (props.onPost != null) { timelineBody = ( <> {timelineBody}
); } } } else { timelineBody = ; } const { CardComponent } = props; body = ( <>
{ const newState = !infoCardCollapse; setInfoCardCollapse(newState); window.localStorage.setItem( genCardCollapseLocalStorageKey(timeline.name), newState.toString() ); }} className="float-right m-1 info-card-collapse-button" />
{timelineBody} ); } else { body = ; } } return ( <>
{body}
); }