"use client"; import { memo, useRef, useState, type Ref } from "react"; import { SessionPanel, SessionPanelContent } from "@kandev/ui/pannel-session"; import { FileBrowser } from "@/components/task/file-browser"; import type { OpenFileTab } from "@/lib/types/backend"; import { useFilesPanelData } from "./task-files-panel-hooks"; import { useAppStore } from "@/components/state-provider"; import { AddWorkspaceSourcesDialog } from "./add-workspace-sources/add-workspace-sources-dialog"; import { ArchivedPanelPlaceholder, useIsTaskArchived } from "./task-archived-context"; import { getAddSourcesDisabledReason, hasActiveTaskSourceWork as getHasActiveTaskSourceWork, } from "./add-workspace-sources/add-workspace-sources-availability"; import { useTranslation } from "react-i18next"; function FilesTabContent({ sessionId, onOpenFile, handleCreateFile, hookDeleteFile, hookRenameFile, hookDownloadFile, activeFilePath, onAddSources, addSourcesButtonRef, addSourcesDisabledReason, }: { sessionId: string | null; onOpenFile: (file: OpenFileTab) => void; handleCreateFile: (path: string) => Promise; hookDeleteFile: (path: string) => Promise; hookRenameFile: (oldPath: string, newPath: string) => Promise; hookDownloadFile: (path: string) => Promise; activeFilePath?: string | null; onAddSources?: (opener: HTMLButtonElement) => void; addSourcesButtonRef?: Ref; addSourcesDisabledReason?: string; }) { const { t } = useTranslation(); if (!sessionId) { return (
{t("task:noTaskSelected")}
); } return ( ); } type TaskFilesPanelProps = { onOpenFile: (file: OpenFileTab) => void; activeFilePath?: string | null; }; const TaskFilesPanel = memo(function TaskFilesPanel({ onOpenFile, activeFilePath, }: TaskFilesPanelProps) { const { t } = useTranslation(); const [addSourcesOpen, setAddSourcesOpen] = useState(false); const [addSourcesOpener, setAddSourcesOpener] = useState(null); const addSourcesButtonRef = useRef(null); const isArchived = useIsTaskArchived(); const activeTask = useAppStore((state) => state.kanban.tasks.find((task) => task.id === state.tasks.activeTaskId), ); const { activeSessionId, hookDeleteFile, hookRenameFile, hookDownloadFile, handleCreateFile } = useFilesPanelData(onOpenFile); const workspaceId = useAppStore((state) => state.workspaces.activeId); const hasActiveTaskSourceWork = useAppStore((state) => { if (!activeTask) return false; const sessionIds = state.taskSessionsByTask.itemsByTaskId[activeTask.id]?.map((session) => session.id) ?? [activeSessionId].filter((sessionId): sessionId is string => Boolean(sessionId)); return getHasActiveTaskSourceWork(sessionIds, state.turns.activeBySession); }); const sourceStateLoading = useAppStore((state) => Boolean( state.kanban.isLoading || (workspaceId && state.repositories.loadingByWorkspaceId[workspaceId]) || (activeTask && state.taskSessionsByTask.loadingByTaskId[activeTask.id]), ), ); const addSourcesDisabledReason = getAddSourcesDisabledReason({ isLoading: sourceStateLoading, hasActiveTurn: hasActiveTaskSourceWork, }); const hasRepository = Boolean(activeTask?.repositoryId || activeTask?.repositories?.length); const resolvedAddSourcesDisabledReason = hasRepository ? addSourcesDisabledReason : t("task:taskNeedsRepositoryForSources"); if (isArchived) return ; return ( { setAddSourcesOpener(opener); setAddSourcesOpen(true); } : undefined } addSourcesButtonRef={addSourcesButtonRef} addSourcesDisabledReason={resolvedAddSourcesDisabledReason} /> {activeTask && hasRepository ? ( ) : null} ); }); export { TaskFilesPanel };