import { CheckCircle2, CircleDot, DownloadCloud, ExternalLink, FileCode2, FolderOpen, GitCommitHorizontal, GitMerge, GitPullRequest, Loader2, MessageCircle, Plus, RefreshCw, SquareTerminal, UploadCloud, Users, } from "lucide-react"; import type * as React from "react"; import type { Project, ProjectIssue, ProjectPullRequest, ProjectRepoContributor, ProjectRepoFile, ProjectRepoSnapshot, Repository, } from "@/features/projects/hooks"; import { projectExternalRefUrl } from "@/features/projects/lib/projectExternalUrl"; import { type ProjectSelectionItem, projectSelectionPresentation, } from "@/features/projects/lib/projectSelection"; import { useProjectSelection } from "@/features/projects/lib/useProjectSelection"; import type { UserProfileLookup } from "@/features/profile/lib/identity"; import { RightAuxiliaryPane } from "@/features/channels/ui/RightAuxiliaryPane"; import { normalizePubkey } from "@/shared/lib/pubkey"; import { Button } from "@/shared/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip"; import { UserAvatar } from "@/shared/ui/UserAvatar"; import { RepoSourceDropdown, type RepoSourceHeaderControls, RepositoryBranchDropdown, } from "./ProjectRepositorySource"; import { ProjectRepositoryManagement } from "./ProjectRepositoryManagement"; import { ProjectWorkItemContextActions } from "./ProjectWorkItemContextActions"; import { ProjectWorkItemCommunicationActions } from "./ProjectWorkItemCommunicationActions"; import { ProjectWorkItemContextDetails } from "./ProjectWorkItemContextDetails"; import { ProjectsSelectionCountMenu } from "./ProjectsSelectionCountMenu"; import { projectReviewActivity, projectRightPanelScope, projectTaskActivity, } from "./projectRightPanelContext"; import { PROJECT_CONTEXT_ACTION_BUTTON_CLASS } from "./projectContextActionStyles"; type ProjectRepositoryActionsPanelProps = { activeTab: string; canResetWidth: boolean; contributors: ProjectRepoContributor[]; contextItem?: ProjectSelectionItem | null; createIssuePending: boolean; detached?: boolean; files: ProjectRepoFile[]; identityPubkey?: string; issues: ProjectIssue[]; onChatWithAgent: (items: ProjectSelectionItem[]) => void; onCreateTask: () => void; onCreatePullRequest?: () => void; onOpenLocalRepository: () => void; onOpenTerminal: () => void; onRepositoryChange: (repositoryId: string) => void; onResetWidth: () => void; onResizeStart: (event: React.PointerEvent) => void; profiles?: UserProfileLookup; pullRequests: ProjectPullRequest[]; project: Project; projects: Project[]; repository: Repository; selectedIssue?: ProjectIssue | null; selectedPullRequest?: ProjectPullRequest | null; snapshot: ProjectRepoSnapshot | null | undefined; sourceControls: RepoSourceHeaderControls; terminalTitle?: string; widthPx: number; }; function RepositoryPanelSection({ children, divided = false, title, }: { children: React.ReactNode; divided?: boolean; title?: string; }) { return (
{title ? (

{title}

) : null} {children}
); } function RepositoryPeople({ people, profiles, }: { people: string[]; profiles?: UserProfileLookup; }) { return (
{people.slice(0, 18).map((person) => { const profile = profiles?.[person]; const label = profile?.displayName?.trim() || profile?.nip05Handle?.trim() || person; return ( {label} ); })}
); } function RepositoryActionButton({ children, disabled, onClick, title, }: { children: React.ReactNode; disabled?: boolean; onClick: () => void; title?: string; }) { return ( ); } export function ProjectRepositoryActionsPanel({ activeTab, canResetWidth, contributors, contextItem, createIssuePending, detached = false, files, identityPubkey, issues, onChatWithAgent, onCreateTask, onCreatePullRequest, onOpenLocalRepository, onOpenTerminal, onRepositoryChange, onResetWidth, onResizeStart, profiles, pullRequests, project, projects, repository, selectedIssue, selectedPullRequest, snapshot, sourceControls, terminalTitle, widthPx, }: ProjectRepositoryActionsPanelProps) { const contextPeople = selectedIssue ? [selectedIssue.author, ...selectedIssue.assignees] : selectedPullRequest ? [ selectedPullRequest.author, ...selectedPullRequest.reviewers, ...selectedPullRequest.approvals.map(({ author }) => author), ...selectedPullRequest.changeRequests.map(({ author }) => author), ] : [repository.owner, ...repository.contributors]; const people = [ ...new Set(contextPeople.filter(Boolean).map(normalizePubkey)), ]; const selection = useProjectSelection(); const selectionPresentation = projectSelectionPresentation( selection?.items ?? [], ); const latestCommit = snapshot?.latestCommit ?? null; const scope = projectRightPanelScope(activeTab); const branchScoped = scope === "branch"; const taskActivity = projectTaskActivity(issues); const reviewActivity = projectReviewActivity(pullRequests); const cloneAction = sourceControls.localDisabled ? sourceControls.onCloneLocal : undefined; const fetchAction = branchScoped && (sourceControls.source === "local" || sourceControls.remoteKind !== "external") ? sourceControls.onFetch : undefined; const pullAction = branchScoped && sourceControls.canPull ? sourceControls.onPull : undefined; const pushAction = branchScoped && sourceControls.canPush ? sourceControls.onPush : undefined; const externalOpenUrl = projectExternalRefUrl( sourceControls.externalUrl, branchScoped ? (sourceControls.selectedTag ?? sourceControls.branch) : null, ); return (
{selectionPresentation && selection ? ( ) : ( <>

{selectedIssue?.title ?? selectedPullRequest?.title ?? repository.name}

{branchScoped ? (
) : null} )}
{contextItem ? ( ) : null} {branchScoped ? (
) : activeTab === "issues" && !selectionPresentation ? ( Create task ) : null} {branchScoped ? (
{cloneAction ? ( {sourceControls.clonePending ? ( ) : ( )} {sourceControls.clonePending ? "Cloning…" : "Clone"} ) : null} {sourceControls.remoteUnavailableReason === "access" && sourceControls.onAskForAccess ? ( Ask for access ) : null} {fetchAction ? ( {sourceControls.fetchPending ? ( ) : ( )} Fetch ) : null} {pullAction ? ( {sourceControls.pullPending ? ( ) : ( )} Pull {sourceControls.behindCount ? ` ${sourceControls.behindCount}` : ""} ) : null} {pushAction ? ( {sourceControls.pushPending ? ( ) : ( )} Push {sourceControls.aheadCount ? ` ${sourceControls.aheadCount}` : ""} ) : null} Terminal {sourceControls.source === "local" ? ( Open ) : externalOpenUrl ? ( ) : null}
) : null} {branchScoped ? (
Latest
{latestCommit ? latestCommit.hash.slice(0, 7) : "—"}
Files
{snapshot ? files.length : "—"}
Contributors
{snapshot ? contributors.length : "—"}
) : ( <>
{!selectedIssue && !selectedPullRequest && activeTab !== "prs" ? ( <>
{activeTab === "issues" ? "Tasks" : "Active tasks"}
{activeTab === "issues" ? taskActivity.total : taskActivity.active}
{activeTab === "issues" ? ( <>
Active
{taskActivity.active}
Completed
{taskActivity.completed}
) : null} ) : null} {!selectedIssue && !selectedPullRequest && activeTab !== "issues" ? ( <>
{activeTab === "prs" ? "Reviews" : "Open reviews"}
{activeTab === "prs" ? reviewActivity.total : reviewActivity.open}
{activeTab === "prs" ? ( <>
Open
{reviewActivity.open}
Merged
{reviewActivity.merged}
) : null} ) : null}
)}
); }