2026-02-16 14:15:19 +02:00
|
|
|
import React from 'react';
|
|
|
|
|
|
2026-08-18 02:59:04 +03:00
|
|
|
import { ProjectNotesTodoPanel } from '@/components/session/project-context/ProjectNotesTodoPanel';
|
2026-04-12 04:29:35 +08:00
|
|
|
import { useGitStore } from '@/stores/useGitStore';
|
2026-04-18 13:46:57 +03:00
|
|
|
import { useProjectsStore } from '@/stores/useProjectsStore';
|
|
|
|
|
import { useDirectoryStore } from '@/stores/useDirectoryStore';
|
2026-07-27 23:07:42 +03:00
|
|
|
import { formatDirectoryName } from '@/lib/utils';
|
2026-08-21 12:12:40 +03:00
|
|
|
import { useSessionUIStore } from '@/sync/session-ui-store';
|
2026-08-27 20:18:05 +03:00
|
|
|
import { useProjectContextOwner } from '@/hooks/useProjectContextOwner';
|
2026-08-27 18:23:40 +03:00
|
|
|
import { CHAT_DRAFT_PROJECT_ID } from '@/lib/chatDirectories';
|
2026-08-27 20:18:05 +03:00
|
|
|
import type { ProjectRef } from '@/lib/projectContextApi';
|
2026-08-21 12:12:40 +03:00
|
|
|
import { useI18n } from '@/lib/i18n';
|
2026-04-12 04:29:35 +08:00
|
|
|
|
2026-08-01 21:16:36 +03:00
|
|
|
export const ProjectContextPanel: React.FC<{
|
|
|
|
|
onActionComplete?: () => void;
|
2026-08-27 20:18:05 +03:00
|
|
|
onOpenPlan?: (plan: { id: string; title: string; projectRef: ProjectRef }) => void;
|
2026-08-01 21:16:36 +03:00
|
|
|
}> = ({ onActionComplete, onOpenPlan }) => {
|
2026-04-18 13:46:57 +03:00
|
|
|
const homeDirectory = useDirectoryStore((state) => state.homeDirectory);
|
2026-08-21 12:12:40 +03:00
|
|
|
const { t } = useI18n();
|
2026-04-18 13:46:57 +03:00
|
|
|
const gitDirectories = useGitStore((state) => state.directories);
|
2026-08-21 12:12:40 +03:00
|
|
|
const chatSessionDirectory = useSessionUIStore((state) => state.currentSessionDirectory);
|
2026-08-27 20:18:05 +03:00
|
|
|
|
|
|
|
|
// One owner decision shared with the panel, agent memory, and PlanView:
|
|
|
|
|
// chats resolve to the Chats owner, worktrees to their project, and an
|
|
|
|
|
// unrecognized directory owns nothing (null) rather than borrowing
|
|
|
|
|
// whichever project happens to be active.
|
2026-08-27 18:23:40 +03:00
|
|
|
const projectRef = useProjectContextOwner(chatSessionDirectory);
|
2026-04-18 13:46:57 +03:00
|
|
|
|
2026-08-27 20:18:05 +03:00
|
|
|
// Display-only lookup: a user-renamed project label wins over the directory
|
|
|
|
|
// name. The owner decision stays with the hook — this must not reintroduce
|
|
|
|
|
// a fallback.
|
|
|
|
|
const projects = useProjectsStore((state) => state.projects);
|
|
|
|
|
const labeledProject = React.useMemo(
|
|
|
|
|
() => (projectRef ? projects.find((project) => project.id === projectRef.id) ?? null : null),
|
|
|
|
|
[projectRef, projects],
|
|
|
|
|
);
|
2026-04-18 13:46:57 +03:00
|
|
|
|
|
|
|
|
const projectLabel = React.useMemo(() => {
|
2026-08-27 20:18:05 +03:00
|
|
|
if (!projectRef) {
|
2026-04-18 13:46:57 +03:00
|
|
|
return null;
|
|
|
|
|
}
|
2026-08-27 20:18:05 +03:00
|
|
|
if (projectRef.id === CHAT_DRAFT_PROJECT_ID) {
|
|
|
|
|
return t('sessions.sidebar.activity.chatsTitle');
|
|
|
|
|
}
|
|
|
|
|
return labeledProject?.label?.trim()
|
|
|
|
|
|| formatDirectoryName(projectRef.path, homeDirectory)
|
|
|
|
|
|| projectRef.path;
|
|
|
|
|
}, [homeDirectory, labeledProject, projectRef, t]);
|
2026-04-18 13:46:57 +03:00
|
|
|
|
|
|
|
|
const canCreateWorktree = React.useMemo(() => {
|
2026-08-27 20:18:05 +03:00
|
|
|
if (!projectRef || projectRef.id === CHAT_DRAFT_PROJECT_ID) {
|
2026-04-18 13:46:57 +03:00
|
|
|
return false;
|
|
|
|
|
}
|
2026-08-27 20:18:05 +03:00
|
|
|
return gitDirectories.get(projectRef.path)?.isGitRepo === true;
|
|
|
|
|
}, [gitDirectories, projectRef]);
|
2026-04-18 13:46:57 +03:00
|
|
|
|
|
|
|
|
return (
|
2026-08-18 02:59:04 +03:00
|
|
|
/* The panel scrolls its own tab content; a scroller here would nest. */
|
|
|
|
|
<div className="h-full min-h-0 overflow-hidden bg-background">
|
2026-04-18 13:46:57 +03:00
|
|
|
<ProjectNotesTodoPanel
|
|
|
|
|
projectRef={projectRef}
|
|
|
|
|
projectLabel={projectLabel}
|
|
|
|
|
canCreateWorktree={canCreateWorktree}
|
2026-08-01 21:16:36 +03:00
|
|
|
onActionComplete={onActionComplete}
|
|
|
|
|
onOpenPlan={onOpenPlan}
|
2026-04-18 13:46:57 +03:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|