All files / client/src/hooks useFileSystem.ts

95% Statements 19/20
76.92% Branches 10/13
100% Functions 4/4
100% Lines 19/19

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144                                                                                                                                                        8x 8x 8x     8x       8x         8x   9x 1x 1x     1x 1x   1x 1x 1x                 1x 1x               8x 3x     8x                                      
/**
 * useFileSystem Hook
 *
 * Orchestrates file system operations and state management.
 * Aggregates sketch management, code editor state, and file I/O operations.
 *
 * This hook coordinates:
 * - Current sketch selection and caching
 * - Code editor content tracking
 * - Modification state (isModified flag)
 * - Integration with sketch tabs and file manager
 */
 
import { useState, useCallback, useEffect, Dispatch, SetStateAction } from "react";
import type { Sketch } from "@shared/schema";
import { useSketchTabs } from "./use-sketch-tabs";
import { useFileManager } from "./use-file-manager";
 
/**
 * File system state and operations
 */
interface FileSystemState {
  /** Currently active sketch */
  currentSketch: Sketch | null;
  /** Code content in the editor */
  code: string;
  /** Whether the current code has unsaved changes */
  isModified: boolean;
}
 
/**
 * File system operations
 */
interface FileSystemOperations {
  /** Set the active sketch */
  setCurrentSketch: Dispatch<SetStateAction<Sketch | null>>;
  /** Update the code content */
  setCode: Dispatch<SetStateAction<string>>;
  /** Mark code as modified or saved */
  setIsModified: Dispatch<SetStateAction<boolean>>;
  /** Initialize default sketch when available */
  initializeDefaultSketch: (sketches: Sketch[] | undefined) => void;
}
 
/**
 * Return type for useFileSystem hook
 */
interface UseFileSystemResult extends FileSystemState, FileSystemOperations {
  /** Access to sketch tabs management */
  tabs: ReturnType<typeof useSketchTabs>["tabs"];
  activeTabId: ReturnType<typeof useSketchTabs>["activeTabId"];
  setActiveTabId: ReturnType<typeof useSketchTabs>["setActiveTabId"];
  setTabs: ReturnType<typeof useSketchTabs>["setTabs"];
  /** Access to file manager operations */
  fileInputRef: ReturnType<typeof useFileManager>["fileInputRef"];
  onLoadFiles: ReturnType<typeof useFileManager>["onLoadFiles"];
  downloadAllFiles: ReturnType<typeof useFileManager>["downloadAllFiles"];
  handleHiddenFileInput: ReturnType<typeof useFileManager>["handleHiddenFileInput"];
}
 
/**
 * Parameters for useFileSystem
 */
interface UseFileSystemParams {
  /** Sketches available from the sketch tabs hook result */
  sketches: Sketch[] | undefined;
}
 
/**
 * Hook that manages file system state and operations.
 * Provides a unified interface for sketch management and code editing.
 *
 * @param params Configuration with available sketches
 * @returns File system state, operations, and integrated sub-hook interfaces
 */
export function useFileSystem(params: UseFileSystemParams): UseFileSystemResult {
  const [currentSketch, setCurrentSketch] = useState<Sketch | null>(null);
  const [code, setCode] = useState("");
  const [isModified, setIsModified] = useState(false);
 
  // Get sketch tabs management
  const { tabs, setTabs, activeTabId, setActiveTabId } = useSketchTabs();
 
  // Get file manager for I/O operations
  // Pass minimal required params: tabs (empty array if not available)
  const fileManager = useFileManager({
    tabs: tabs || [],
  });
 
  // Initialize default sketch when sketches become available
  const initializeDefaultSketch = useCallback(
    (availableSketches: Sketch[] | undefined) => {
      if (availableSketches && availableSketches.length > 0 && !currentSketch) {
        const defaultSketch = availableSketches[0];
        setCurrentSketch(defaultSketch);
 
        // Ensure the default sketch is visible as a tab (so the user can’t accidentally close it)
        setTabs((prevTabs) => {
          Iif (prevTabs.length > 0) return prevTabs;
 
          const tabId = `tab-${Date.now()}-${crypto.randomUUID().slice(0, 7)}`;
          setActiveTabId(tabId);
          return [
            {
              id: tabId,
              name: defaultSketch.name,
              content: defaultSketch.content,
            },
          ];
        });
 
        Eif (!code && defaultSketch.content) {
          setCode(defaultSketch.content);
        }
      }
    },
    [currentSketch, code, setActiveTabId, setTabs, setCode],
  );
 
  // Initialize on sketch load
  useEffect(() => {
    initializeDefaultSketch(params.sketches);
  }, [params.sketches, initializeDefaultSketch]);
 
  return {
    // State
    currentSketch,
    code,
    isModified,
    // Operations
    setCurrentSketch,
    setCode,
    setIsModified,
    initializeDefaultSketch,
    // Sketch tabs integration
    tabs,
    activeTabId,
    setActiveTabId,
    setTabs,
    // File manager integration
    ...fileManager,
  };
}