Files
claude-mem/src/ui/viewer/hooks/useContextPreview.ts
T
Alex Newman bfc7de377a revert: roll back v12.3.3 (Issue Blowout 2026)
SessionStart context injection regressed in v12.3.3 — no memory
context is being delivered to new sessions. Rolling back to the
v12.3.2 tree state while the regression is investigated.

Reverts #2080.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 11:59:15 -07:00

140 lines
4.1 KiB
TypeScript

import { useState, useEffect, useCallback } from 'react';
import type { ProjectCatalog, Settings } from '../types';
interface UseContextPreviewResult {
preview: string;
isLoading: boolean;
error: string | null;
refresh: () => Promise<void>;
projects: string[];
sources: string[];
selectedSource: string | null;
setSelectedSource: (source: string) => void;
selectedProject: string | null;
setSelectedProject: (project: string) => void;
}
function getPreferredSource(sources: string[]): string | null {
if (sources.includes('claude')) return 'claude';
if (sources.includes('codex')) return 'codex';
return sources[0] || null;
}
function withDefaultSources(sources: string[]): string[] {
const merged = ['claude', 'codex', ...sources];
return Array.from(new Set(merged));
}
export function useContextPreview(settings: Settings): UseContextPreviewResult {
const [preview, setPreview] = useState<string>('');
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [catalog, setCatalog] = useState<ProjectCatalog>({ projects: [], sources: [], projectsBySource: {} });
const [projects, setProjects] = useState<string[]>([]);
const [selectedSource, setSelectedSource] = useState<string | null>(null);
const [selectedProject, setSelectedProject] = useState<string | null>(null);
// Fetch projects on mount
useEffect(() => {
async function fetchProjects() {
let data: ProjectCatalog;
try {
const response = await fetch('/api/projects');
data = await response.json() as ProjectCatalog;
} catch (err: unknown) {
console.error('Failed to fetch projects:', err instanceof Error ? err.message : String(err));
return;
}
const nextCatalog: ProjectCatalog = {
projects: data.projects || [],
sources: withDefaultSources(data.sources || []),
projectsBySource: data.projectsBySource || {}
};
setCatalog(nextCatalog);
const preferredSource = getPreferredSource(nextCatalog.sources);
setSelectedSource(preferredSource);
if (preferredSource) {
const sourceProjects = nextCatalog.projectsBySource[preferredSource] || [];
setProjects(sourceProjects);
setSelectedProject(sourceProjects[0] || null);
return;
}
setProjects(nextCatalog.projects);
setSelectedProject(nextCatalog.projects[0] || null);
}
fetchProjects();
}, []);
useEffect(() => {
if (!selectedSource) {
setProjects(catalog.projects);
setSelectedProject(prev => (prev && catalog.projects.includes(prev) ? prev : catalog.projects[0] || null));
return;
}
const sourceProjects = catalog.projectsBySource[selectedSource] || [];
setProjects(sourceProjects);
setSelectedProject(prev => (prev && sourceProjects.includes(prev) ? prev : sourceProjects[0] || null));
}, [catalog, selectedSource]);
const refresh = useCallback(async () => {
if (!selectedProject) {
setPreview('No project selected');
return;
}
setIsLoading(true);
setError(null);
const params = new URLSearchParams({
project: selectedProject
});
if (selectedSource) {
params.append('platformSource', selectedSource);
}
try {
const response = await fetch(`/api/context/preview?${params}`);
const text = await response.text();
if (response.ok) {
setPreview(text);
} else {
setError('Failed to load preview');
}
} catch (error: unknown) {
console.error('Failed to load context preview:', error instanceof Error ? error.message : String(error));
setError('Failed to load preview');
}
setIsLoading(false);
}, [selectedProject, selectedSource]);
// Debounced refresh when settings or selectedProject change
useEffect(() => {
const timeout = setTimeout(() => {
refresh();
}, 300);
return () => clearTimeout(timeout);
}, [settings, refresh]);
return {
preview,
isLoading,
error,
refresh,
projects,
sources: catalog.sources,
selectedSource,
setSelectedSource,
selectedProject,
setSelectedProject
};
}