import { useCallback, useEffect, useRef, useState } from "react"; import { Activity, ActivityType } from "../network/models.ts"; import { network } from "../network/network.ts"; import showToast from "../components/toast.ts"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router"; import Loading from "../components/loading.tsx"; import { CommentContent } from "../components/comment_tile.tsx"; import { MdOutlineArchive, MdOutlinePhotoAlbum } from "react-icons/md"; import Badge from "../components/badge.tsx"; export default function ActivitiesPage() { const [activities, setActivities] = useState([]); const pageRef = useRef(0); const maxPageRef = useRef(1); const isLoadingRef = useRef(false); const fetchNextPage = useCallback(async () => { if (isLoadingRef.current || pageRef.current >= maxPageRef.current) return; isLoadingRef.current = true; const response = await network.getActivities(pageRef.current + 1); if (response.success) { setActivities((prev) => [...prev, ...response.data!]); pageRef.current += 1; maxPageRef.current = response.totalPages!; } else { showToast({ type: "error", message: response.message || "Failed to load activities", }); } isLoadingRef.current = false; }, []); useEffect(() => { fetchNextPage(); }, [fetchNextPage]); useEffect(() => { const handleScroll = () => { if ( window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 100 && !isLoadingRef.current && pageRef.current < maxPageRef.current ) { fetchNextPage(); } }; window.addEventListener("scroll", handleScroll); return () => window.removeEventListener("scroll", handleScroll); }, [fetchNextPage]); return (
{activities.map((activity) => ( ))} {pageRef.current < maxPageRef.current && }
); } function fileSizeToString(size: number) { if (size < 1024) { return size + "B"; } else if (size < 1024 * 1024) { return (size / 1024).toFixed(2) + "KB"; } else if (size < 1024 * 1024 * 1024) { return (size / 1024 / 1024).toFixed(2) + "MB"; } else { return (size / 1024 / 1024 / 1024).toFixed(2) + "GB"; } } function ActivityCard({ activity }: { activity: Activity }) { const { t } = useTranslation(); const messages = [ "Unknown activity", t("Published a resource"), t("Updated a resource"), t("Posted a comment"), t("Added a new file"), ]; const navigate = useNavigate(); let content = <>; if ( activity.type === ActivityType.ResourcePublished || activity.type === ActivityType.ResourceUpdated ) { content = (
{activity.resource?.title}
{activity.resource?.image && (
{activity.resource.title}
)}
); } else if (activity.type === ActivityType.NewComment) { content = (
); } else if (activity.type === ActivityType.NewFile) { content = (

{activity.file!.filename}

{activity.file!.description}

{activity.file!.is_redirect ? t("Redirect") : fileSizeToString(activity.file!.size)} {(() => { let title = activity.resource!.title; if (title.length > 20) { title = title.slice(0, 20) + "..."; } return title; })()}

); } return (
{ if ( activity.type === ActivityType.ResourcePublished || activity.type === ActivityType.ResourceUpdated ) { navigate(`/resources/${activity.resource?.id}`); } else if (activity.type === ActivityType.NewComment) { navigate(`/comments/${activity.comment?.id}`); } else if (activity.type === ActivityType.NewFile) { navigate(`/resources/${activity.resource?.id}#files`); } }} >
{"avatar"}
{activity.user?.username} {messages[activity.type]}
{content}
); }