import { Link, useLocation, useParams } from "react-router-dom"; import { ChevronRight, Home, Settings } from "lucide-react"; import { useProjectLayout } from "@/app/project/layout"; import { useProjectsQuery } from "@/hooks/useProjectsQuery"; import { useOptionalRoom } from "@/contexts/room"; import { useState } from "react"; import { RoomSettingsModal } from "@/app/project/channel/RoomSettingsModal"; const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i; function truncateUuid(s: string): string { return s.slice(0, 8); } interface BreadcrumbSegment { label: string; path: string; isLast: boolean; fullUuid?: string; } function useBreadcrumbs(): BreadcrumbSegment[] { const location = useLocation(); const params = useParams<{ projectName?: string; repoName?: string; issueNumber?: string; skillSlug?: string; roomId?: string; }>(); const roomContext = useOptionalRoom(); const currentRoom = roomContext?.currentRoom; const { data: projects = [] } = useProjectsQuery(); const activeProject = projects.find((p) => p.name === params.projectName); const segments: BreadcrumbSegment[] = []; const pathParts = location.pathname.split("/").filter(Boolean); for (let i = 0; i < pathParts.length; i++) { const part = pathParts[i]; const path = "/" + pathParts.slice(0, i + 1).join("/"); const isLast = i === pathParts.length - 1; let label = part; let fullUuid: string | undefined; if (UUID_RE.test(part)) { fullUuid = part; label = truncateUuid(part); } else if (part === params.projectName && activeProject) { label = activeProject.display_name; } else if (part === params.repoName) { label = part; } else if (part === params.issueNumber) { label = `#${part}`; } else if (part === params.skillSlug) { label = part; } else if (part === "channel" && params.roomId && currentRoom) { label = currentRoom.room_name; } else { label = part.charAt(0).toUpperCase() + part.slice(1); } segments.push({ label, path, isLast, fullUuid }); } return segments; } const TOOLBAR_ICONS = [ { label: "Pinned Messages", path: "M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z", }, { label: "Search", path: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z", }, { label: "Notifications", path: "M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9", }, { label: "Help", path: "M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.54-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z", }, ]; export function Header() { const location = useLocation(); const segments = useBreadcrumbs(); const { showMembers, setShowMembers } = useProjectLayout(); const [showSettings, setShowSettings] = useState(false); const roomContext = useOptionalRoom(); const handleCopy = (e: React.MouseEvent, text: string) => { e.preventDefault(); navigator.clipboard.writeText(text); }; return ( <> {segments.map((segment, idx) => ( {segment.isLast ? ( handleCopy(e, segment.fullUuid!) } : {})} > {segment.label} ) : segment.fullUuid ? ( handleCopy(e, segment.fullUuid!)} > {segment.label} ) : ( {segment.label} )} ))} {location.pathname.startsWith("/me") ? null : ( <> {roomContext?.currentRoom && location.pathname.includes("/channel/") && ( setShowSettings(true)} className="w-8 h-8 flex items-center justify-center rounded-[4px] transition-colors hover:bg-hover-bg" style={{ color: "var(--text-secondary)" }} title="Room Settings" > )} setShowMembers(!showMembers)} className="w-8 h-8 flex items-center justify-center rounded-[4px] transition-colors" style={ showMembers ? { color: "var(--text-primary)", backgroundColor: "var(--hover-bg-strong)", } : { color: "var(--text-secondary)" } } > {TOOLBAR_ICONS.map((icon, i) => ( ))} > )} > ); }