import React, { useState, useEffect, useRef } from "react"; import { observer } from "mobx-react"; import { useParams } from "next/navigation"; import Masonry from "react-masonry-component"; import useSWR from "swr"; import { Loader } from "@plane/ui"; import { cn } from "@plane/utils"; import { useIntersectionObserver } from "@/hooks/use-intersection-observer"; import { useSticky } from "@/hooks/use-stickies"; import { STICKY_COLORS } from "../editor/sticky-editor/color-pallete"; import { EmptyState } from "./empty"; import { StickyNote } from "./sticky"; import { useStickyOperations } from "./sticky/use-operations"; const PER_PAGE = 10; type TProps = { columnCount: number; }; export const StickyAll = observer((props: TProps) => { const { columnCount } = props; // refs const masonryRef = useRef(null); const containerRef = useRef(null); // states const [containerHeight, setContainerHeight] = useState(0); const [showAllStickies, setShowAllStickies] = useState(false); const [intersectionElement, setIntersectionElement] = useState(null); // router const { workspaceSlug } = useParams(); // hooks const { stickyOperations } = useStickyOperations({ workspaceSlug: workspaceSlug?.toString() }); const { fetchingWorkspaceStickies, toggleShowNewSticky, getWorkspaceStickies, fetchWorkspaceStickies, currentPage, totalPages, incrementPage, creatingSticky, } = useSticky(); const workspaceStickies = getWorkspaceStickies(workspaceSlug?.toString()); const itemWidth = `${100 / columnCount}%`; useSWR( workspaceSlug ? `WORKSPACE_STICKIES_${workspaceSlug}_${PER_PAGE}:${currentPage}:0` : null, workspaceSlug ? () => fetchWorkspaceStickies(workspaceSlug.toString(), `${PER_PAGE}:${currentPage}:0`, PER_PAGE) : null ); useEffect(() => { if (!fetchingWorkspaceStickies && workspaceStickies.length === 0) { toggleShowNewSticky(true); } }, [fetchingWorkspaceStickies, workspaceStickies, toggleShowNewSticky]); // Update this useEffect to correctly track height useEffect(() => { if (!masonryRef?.current) return; const updateHeight = () => { if (masonryRef.current) { const height = masonryRef.current.getBoundingClientRect().height; setContainerHeight(parseInt(height.toString())); } }; // Initial height measurement updateHeight(); // Create ResizeObserver const resizeObserver = new ResizeObserver(() => { updateHeight(); }); resizeObserver.observe(masonryRef.current); // Also update height when Masonry content changes const mutationObserver = new MutationObserver(() => { updateHeight(); }); mutationObserver.observe(masonryRef.current, { childList: true, subtree: true, attributes: true, }); return () => { resizeObserver.disconnect(); mutationObserver.disconnect(); }; }, [masonryRef?.current]); useIntersectionObserver(containerRef, fetchingWorkspaceStickies ? null : intersectionElement, incrementPage, "20%"); if (fetchingWorkspaceStickies && workspaceStickies.length === 0) { return (
); } const getStickiesToRender = () => { let stickies: (string | undefined)[] = workspaceStickies; if (currentPage + 1 < totalPages && stickies.length >= PER_PAGE) { stickies = [...stickies, undefined]; } return stickies; }; const stickyIds = getStickiesToRender(); const childElements = stickyIds.map((stickyId, index) => (
{index === stickyIds.length - 1 && currentPage + 1 < totalPages ? (
) : ( )}
)); if (!fetchingWorkspaceStickies && workspaceStickies.length === 0) return ( { toggleShowNewSticky(true); stickyOperations.create({ color: STICKY_COLORS[0] }); }} /> ); return (
{/* @ts-expect-error type mismatch here */} {childElements}
{containerHeight > 632.9 && (
)}
); }); export const StickiesLayout = () => { // states const [containerWidth, setContainerWidth] = useState(null); // refs const ref = useRef(null); useEffect(() => { if (!ref?.current) return; setContainerWidth(ref?.current.offsetWidth); const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { setContainerWidth(entry.contentRect.width); } }); resizeObserver.observe(ref?.current); return () => resizeObserver.disconnect(); }, []); const getColumnCount = (width: number | null): number => { if (width === null) return 4; if (width < 640) return 2; // sm if (width < 768) return 3; // md if (width < 1024) return 4; // lg if (width < 1280) return 5; // xl return 6; // 2xl and above }; const columnCount = getColumnCount(containerWidth); return (
); };