File size: 2,347 Bytes
246d201
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import React from "react";
import { useSelector } from "react-redux";

import { useFiles } from "#/context/files";
import { cn } from "#/utils/utils";
import { useListFiles } from "#/hooks/query/use-list-files";
import { useListFile } from "#/hooks/query/use-list-file";
import { Filename } from "./filename";
import { RootState } from "#/store";

interface TreeNodeProps {
  path: string;
  defaultOpen?: boolean;
}

function TreeNode({ path, defaultOpen = false }: TreeNodeProps) {
  const { setFileContent, setSelectedPath, files, selectedPath } = useFiles();
  const [isOpen, setIsOpen] = React.useState(defaultOpen);
  const { curAgentState } = useSelector((state: RootState) => state.agent);

  const isDirectory = path.endsWith("/");

  const { data: paths } = useListFiles({
    path,
    enabled: isDirectory && isOpen,
  });

  const { data: fileContent, refetch } = useListFile({ path });

  React.useEffect(() => {
    if (fileContent) {
      if (fileContent !== files[path]) {
        setFileContent(path, fileContent);
      }
    }
  }, [fileContent, path]);

  React.useEffect(() => {
    if (selectedPath === path && !isDirectory) {
      refetch();
    }
  }, [curAgentState, selectedPath, path, isDirectory]);

  const fileParts = path.split("/");
  const filename =
    fileParts[fileParts.length - 1] || fileParts[fileParts.length - 2];

  const handleClick = async () => {
    if (isDirectory) setIsOpen((prev) => !prev);
    else {
      setSelectedPath(path);
      await refetch();
    }
  };

  return (
    <div

      className={cn(

        "text-sm text-neutral-400",

        path === selectedPath && "bg-gray-700",

      )}

    >

      <button

        type={isDirectory ? "button" : "submit"}

        name="file"

        value={path}

        onClick={handleClick}

        className="flex items-center justify-between w-full px-1"

      >

        <Filename

          name={filename}

          type={isDirectory ? "folder" : "file"}

          isOpen={isOpen}

        />

      </button>



      {isOpen && paths && (

        <div className="ml-5">

          {paths.map((child, index) => (

            <TreeNode key={index} path={child} />

          ))}

        </div>

      )}

    </div>
  );
}

export default React.memo(TreeNode);