Fixes state management loops around getting results V2 (#5153)

Makes sure settings step collapses in results step

Makes sure result step doesn't always reset even in development for
baseTool

Make sure result step doesn't reset for convert
This commit is contained in:
ConnorYoh 2025-12-03 17:42:04 +00:00 committed by GitHub
parent f2bffe2dc6
commit e59c717dc0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 73 additions and 16 deletions

View File

@ -87,6 +87,7 @@ export function createToolFlow<TParams = unknown>(config: ToolFlowConfig<TParams
{config.steps.map((stepConfig) =>
steps.create(stepConfig.title, {
isVisible: stepConfig.isVisible,
isCollapsed: stepConfig.isCollapsed,
onCollapsedClick: stepConfig.onCollapsedClick,
tooltip: stepConfig.tooltip
}, stepConfig.content)

View File

@ -47,6 +47,10 @@ export function useBaseTool<TParams, TParamsHook extends BaseParametersHook<TPar
const { selectedFiles } = useFileSelection();
const previousFileCount = useRef(selectedFiles.length);
// Prevent reset immediately after operation completes (when consumeFiles auto-selects outputs)
const skipNextSelectionResetRef = useRef(false);
const previousSelectionRef = useRef<string>('');
// Tool-specific hooks
const params = useParams();
const operation = useOperation();
@ -54,19 +58,45 @@ export function useBaseTool<TParams, TParamsHook extends BaseParametersHook<TPar
// Endpoint validation using parameters hook
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(params.getEndpointName());
// Standard computed state - defined early so it's available in useEffects
const hasFiles = selectedFiles.length >= minFiles;
const hasResults = operation.files.length > 0 || operation.downloadUrl !== null;
const settingsCollapsed = !hasFiles || hasResults;
// Reset results when parameters change
useEffect(() => {
operation.resetResults();
onPreviewFile?.(null);
}, [params.parameters]);
// Reset results when selected files change
// When operation completes, flag the next selection change to skip reset
// (consumeFiles auto-selects outputs immediately after processing)
useEffect(() => {
if (selectedFiles.length > 0) {
operation.resetResults();
onPreviewFile?.(null);
if (hasResults) {
skipNextSelectionResetRef.current = true;
}
}, [selectedFiles.length]);
}, [hasResults]);
// Reset results when user manually changes file selection
useEffect(() => {
if (selectedFiles.length === 0) return;
const currentSelection = selectedFiles.map(f => f.fileId).sort().join(',');
if (currentSelection === previousSelectionRef.current) return; // No change
// Skip reset if this is the auto-selection after operation completed
if (skipNextSelectionResetRef.current) {
skipNextSelectionResetRef.current = false;
previousSelectionRef.current = currentSelection;
return;
}
// User manually selected different files - reset results
previousSelectionRef.current = currentSelection;
operation.resetResults();
onPreviewFile?.(null);
}, [selectedFiles]);
// Reset parameters when transitioning from 0 files to at least 1 file
useEffect(() => {
@ -101,6 +131,7 @@ export function useBaseTool<TParams, TParamsHook extends BaseParametersHook<TPar
}, [onPreviewFile, toolName]);
const handleSettingsReset = useCallback(() => {
skipNextSelectionResetRef.current = false;
operation.resetResults();
onPreviewFile?.(null);
}, [operation, onPreviewFile]);
@ -110,11 +141,6 @@ export function useBaseTool<TParams, TParamsHook extends BaseParametersHook<TPar
onPreviewFile?.(null);
}, [operation, onPreviewFile]);
// Standard computed state
const hasFiles = selectedFiles.length >= minFiles;
const hasResults = operation.files.length > 0 || operation.downloadUrl !== null;
const settingsCollapsed = !hasFiles || hasResults;
return {
// File management
selectedFiles,

View File

@ -23,6 +23,10 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled(convertParams.getEndpointName());
// Prevent reset immediately after operation completes (when consumeFiles auto-selects outputs)
const skipNextSelectionResetRef = useRef(false);
const previousSelectionRef = useRef<string>('');
const scrollToBottom = () => {
if (scrollContainerRef.current) {
scrollContainerRef.current.scrollTo({
@ -33,24 +37,49 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
};
const hasFiles = selectedFiles.length > 0;
const hasResults = convertOperation.downloadUrl !== null;
const hasResults = convertOperation.files.length > 0 || convertOperation.downloadUrl !== null;
const settingsCollapsed = hasResults;
// When operation completes, flag the next selection change to skip reset
useEffect(() => {
if (hasResults) {
skipNextSelectionResetRef.current = true;
}
}, [hasResults]);
// Reset results when user manually changes file selection
useEffect(() => {
const currentSelection = selectedFiles.map(f => f.fileId).sort().join(',');
if (currentSelection === previousSelectionRef.current) return; // No change
// Skip reset if this is the auto-selection after operation completed
// Don't analyze file types - would change parameters and trigger another reset
if (skipNextSelectionResetRef.current) {
skipNextSelectionResetRef.current = false;
previousSelectionRef.current = currentSelection;
return;
}
// User manually selected different files
if (selectedFiles.length > 0) {
previousSelectionRef.current = currentSelection;
convertParams.analyzeFileTypes(selectedFiles);
if (hasResults) {
convertOperation.resetResults();
onPreviewFile?.(null);
}
} else {
// Only reset when there are no active files at all
// If there are active files but no selected files, keep current format (user filtered by format)
previousSelectionRef.current = '';
if (activeFiles.length === 0) {
convertParams.resetParameters();
}
}
}, [selectedFiles, activeFiles, convertParams.analyzeFileTypes, convertParams.resetParameters]);
}, [selectedFiles]);
useEffect(() => {
// Only clear results if we're not currently processing and parameters changed
if (!convertOperation.isLoading) {
// Reset when user changes conversion parameters (but not during operation)
if (!convertOperation.isLoading && !skipNextSelectionResetRef.current) {
convertOperation.resetResults();
onPreviewFile?.(null);
}
@ -87,6 +116,7 @@ const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => {
};
const handleSettingsReset = () => {
skipNextSelectionResetRef.current = false;
convertOperation.resetResults();
onPreviewFile?.(null);
};