import React, { type JSX, memo, useCallback, useEffect } from 'react';
import { type IPageHasId, isPopulated } 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 { PagePathHierarchicalLink } from '~/components/Common/PagePathHierarchicalLink';
import LinkedPagePath from '~/models/linked-page-path';
import { useSetSearchKeyword } from '~/states/search';
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 (
);
})}
>
);
});
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: JSX.Element | null = null;
if (page.grant !== 1) {
locked = (
lock
);
}
const isTagElementsRendered = !(isSmall || page.tags.length === 0);
return (
{!dPagePath.isRoot && formerLink}
{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 setSearchKeyword = useSetSearchKeyword();
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 (
{data != null &&
data
.flatMap((apiResult) => apiResult.pages)
.map((page) => (
setSearchKeyword(`tag:${tagName}`)}
/>
))}
);
};