import type { EnvironmentThreadShell } from "@t3tools/client-runtime/state/models"; import { scopedThreadKey, scopeThreadRef } from "@t3tools/client-runtime/environment"; import { ChevronDownIcon, SquarePenIcon } from "lucide-react"; import { memo } from "react"; import { cn } from "~/lib/utils"; import type { SidebarProjectSnapshot } from "../../sidebarProjectGrouping"; import { useUiStateStore } from "../../uiStateStore"; import { resolveSidebarFolderDot, resolveThreadLastVisitedAt } from "../Sidebar.logic"; import { ProjectFavicon } from "../ProjectFavicon"; import { Button } from "../ui/button"; const FOLDER_DOT_CLASS_NAME = { attention: "bg-warning", failed: "bg-error", unread: "bg-success", working: "bg-info", } as const; const FOLDER_DOT_LABEL = { attention: ", needs you", failed: ", failed", unread: ", done", working: ", working", } as const; /** The folder's sidebar tree row; its thread rows name it as their parent. */ export function sidebarFolderRowId(projectKey: string) { return `folder:${projectKey}`; } /** * A project folder in the boring sidebar. It reads like a shelf header: a trailing * count and chevron, with the count and a status dot only while it is closed, so a * closed folder still says when a hidden thread needs you. */ export const SidebarProjectFolderHeader = memo(function SidebarProjectFolderHeader(props: { group: SidebarProjectSnapshot; collapsed: boolean; hiddenThreads: readonly EnvironmentThreadShell[]; onToggle: (group: SidebarProjectSnapshot) => void; onNewThread: (group: SidebarProjectSnapshot) => void; onContextMenu: (group: SidebarProjectSnapshot, position: { x: number; y: number }) => void; }) { const { group, collapsed, hiddenThreads } = props; const rowId = sidebarFolderRowId(group.projectKey); const localLastVisitedAtById = useUiStateStore((state) => state.threadLastVisitedAtById); const dot = collapsed ? resolveSidebarFolderDot( hiddenThreads.map((thread) => ({ ...thread, lastVisitedAt: resolveThreadLastVisitedAt( thread.lastVisitedAt, localLastVisitedAtById[ scopedThreadKey(scopeThreadRef(thread.environmentId, thread.id)) ], ), })), ) : null; return (