import React, { memo, useCallback, useEffect, } from 'react'; import { isPopulated, type IPageHasId, } from '@growi/core'; import { DevidedPagePath } from '@growi/core/dist/models'; import { UserPicture } from '@growi/ui/dist/components'; import { useTranslation } from 'react-i18next'; import FormattedDistanceDate from '~/client/components/FormattedDistanceDate'; import InfiniteScroll from '~/client/components/InfiniteScroll'; import { useKeywordManager } from '~/client/services/search-operation'; import { PagePathHierarchicalLink } from '~/components/Common/PagePathHierarchicalLink'; import LinkedPagePath from '~/models/linked-page-path'; import { useSWRINFxRecentlyUpdated } from '~/stores/page-listing'; import loggerFactory from '~/utils/logger'; import { SidebarHeaderReloadButton } from '../SidebarHeaderReloadButton'; import styles from './RecentChangesSubstance.module.scss'; const formerLinkClass = styles['grw-former-link']; const pageItemLowerClass = styles['grw-recent-changes-item-lower']; // eslint-disable-next-line @typescript-eslint/no-unused-vars const logger = loggerFactory('growi:History'); type PageItemLowerProps = { page: IPageHasId, } type PageItemProps = PageItemLowerProps & { isSmall: boolean, onClickTag?: (tagName: string) => void, } const PageItemLower = memo(({ page }: PageItemLowerProps): JSX.Element => { return (
footprint {page.seenUsers.length}
chat {page.commentCount}
); }); PageItemLower.displayName = 'PageItemLower'; type PageTagsProps = PageItemProps; const PageTags = memo((props: PageTagsProps): JSX.Element => { const { page, isSmall, onClickTag } = props; if (isSmall || (page.tags.length === 0)) { return <>; } return ( <> { page.tags.map((tag) => { if (!isPopulated(tag)) { return <>; } return ( onClickTag?.(tag.name)} > {tag.name} ); }) } ); }); PageTags.displayName = 'PageTags'; const PageItem = memo(({ page, isSmall, onClickTag }: PageItemProps): JSX.Element => { const dPagePath = new DevidedPagePath(page.path, false, true); const linkedPagePathFormer = new LinkedPagePath(dPagePath.former); const linkedPagePathLatter = new LinkedPagePath(dPagePath.latter); const FormerLink = () => (
); let locked; if (page.grant !== 1) { locked = lock; } const isTagElementsRendered = !(isSmall || (page.tags.length === 0)); return (
  • { !dPagePath.isRoot && }
    { page.wip && ( WIP ) } {locked}
    { isTagElementsRendered && (
    ) }
  • ); }); PageItem.displayName = 'PageItem'; type HeaderProps = { isSmall: boolean, onSizeChange: (isSmall: boolean) => void, isWipPageShown: boolean, onWipPageShownChange: () => void, } export const RecentChangesHeader = ({ isSmall, onSizeChange, isWipPageShown, onWipPageShownChange, }: HeaderProps): JSX.Element => { const { t } = useTranslation(); const { mutate } = useSWRINFxRecentlyUpdated(isWipPageShown, { suspense: true }); const retrieveSizePreferenceFromLocalStorage = useCallback(() => { if (window.localStorage.isRecentChangesSidebarSmall === 'true') { onSizeChange(true); } }, [onSizeChange]); const changeSizeHandler = useCallback(() => { onSizeChange(!isSmall); window.localStorage.setItem('isRecentChangesSidebarSmall', String(isSmall)); }, [isSmall, onSizeChange]); // componentDidMount useEffect(() => { retrieveSizePreferenceFromLocalStorage(); }, [retrieveSizePreferenceFromLocalStorage]); return ( <> mutate()} />
    ); }; type ContentProps = { isSmall: boolean, isWipPageShown: boolean, } export const RecentChangesContent = ({ isSmall, isWipPageShown }: ContentProps): JSX.Element => { const swrInifinitexRecentlyUpdated = useSWRINFxRecentlyUpdated(isWipPageShown, { suspense: true }); const { data } = swrInifinitexRecentlyUpdated; const { pushState } = useKeywordManager(); const isEmpty = data?.[0]?.pages.length === 0; const lastPageIndex = data?.length ? data.length - 1 : 0; const isReachingEnd = isEmpty || (data != null && lastPageIndex > 0 && data[lastPageIndex]?.pages.length < data[lastPageIndex - 1]?.pages.length); return (
    ); };