Migrate file components

This commit is contained in:
2025-05-18 14:39:17 +02:00
parent 834a7b1e7e
commit db75bdcc89
2 changed files with 67 additions and 28 deletions

View File

@@ -9,7 +9,15 @@ import {
import { useModalContext } from '../../contexts/ModalContext'; import { useModalContext } from '../../contexts/ModalContext';
import { useWorkspace } from '../../contexts/WorkspaceContext'; import { useWorkspace } from '../../contexts/WorkspaceContext';
const FileActions = ({ handlePullChanges, selectedFile }) => { interface FileActionsProps {
handlePullChanges: () => Promise<boolean>;
selectedFile: string | null;
}
const FileActions: React.FC<FileActionsProps> = ({
handlePullChanges,
selectedFile,
}) => {
const { settings } = useWorkspace(); const { settings } = useWorkspace();
const { const {
setNewFileModalVisible, setNewFileModalVisible,
@@ -17,9 +25,9 @@ const FileActions = ({ handlePullChanges, selectedFile }) => {
setCommitMessageModalVisible, setCommitMessageModalVisible,
} = useModalContext(); } = useModalContext();
const handleCreateFile = () => setNewFileModalVisible(true); const handleCreateFile = (): void => setNewFileModalVisible(true);
const handleDeleteFile = () => setDeleteFileModalVisible(true); const handleDeleteFile = (): void => setDeleteFileModalVisible(true);
const handleCommitAndPush = () => setCommitMessageModalVisible(true); const handleCommitAndPush = (): void => setCommitMessageModalVisible(true);
return ( return (
<Group gap="xs"> <Group gap="xs">

View File

@@ -1,21 +1,35 @@
import React, { useRef, useState, useLayoutEffect } from 'react'; import React, { useRef, useState, useLayoutEffect } from 'react';
import { Tree } from 'react-arborist'; import { Tree, NodeApi } from 'react-arborist';
import { IconFile, IconFolder, IconFolderOpen } from '@tabler/icons-react'; import { IconFile, IconFolder, IconFolderOpen } from '@tabler/icons-react';
import { Tooltip } from '@mantine/core'; import { Tooltip } from '@mantine/core';
import useResizeObserver from '@react-hook/resize-observer'; import useResizeObserver from '@react-hook/resize-observer';
import { FileNode } from '../../types/fileApi';
const useSize = (target) => { interface Size {
const [size, setSize] = useState(); width: number;
height: number;
}
interface FileTreeProps {
files: FileNode[];
handleFileSelect: (filePath: string | null) => Promise<void>;
showHiddenFiles: boolean;
}
const useSize = (target: React.RefObject<HTMLElement>): Size | undefined => {
const [size, setSize] = useState<Size>();
useLayoutEffect(() => { useLayoutEffect(() => {
if (target.current) {
setSize(target.current.getBoundingClientRect()); setSize(target.current.getBoundingClientRect());
}
}, [target]); }, [target]);
useResizeObserver(target, (entry) => setSize(entry.contentRect)); useResizeObserver(target, (entry) => setSize(entry.contentRect));
return size; return size;
}; };
const FileIcon = ({ node }) => { const FileIcon = ({ node }: { node: NodeApi<FileNode> }) => {
if (node.isLeaf) { if (node.isLeaf) {
return <IconFile size={16} />; return <IconFile size={16} />;
} }
@@ -26,7 +40,21 @@ const FileIcon = ({ node }) => {
); );
}; };
const Node = ({ node, style, dragHandle }) => { // Define a Node component that matches what React-Arborist expects
function Node(props: any) {
const { node, style, dragHandle } = props;
const handleClick = () => {
if (node.isInternal) {
node.toggle();
} else {
const treeProps = node.tree.props as any;
if (typeof treeProps.onNodeClick === 'function') {
treeProps.onNodeClick(node);
}
}
};
return ( return (
<Tooltip label={node.data.name} openDelay={500}> <Tooltip label={node.data.name} openDelay={500}>
<div <div
@@ -40,13 +68,7 @@ const Node = ({ node, style, dragHandle }) => {
whiteSpace: 'nowrap', whiteSpace: 'nowrap',
overflow: 'hidden', overflow: 'hidden',
}} }}
onClick={() => { onClick={handleClick}
if (node.isInternal) {
node.toggle();
} else {
node.tree.props.onNodeClick(node);
}
}}
> >
<FileIcon node={node} /> <FileIcon node={node} />
<span <span
@@ -63,13 +85,17 @@ const Node = ({ node, style, dragHandle }) => {
</div> </div>
</Tooltip> </Tooltip>
); );
}; }
const FileTree = ({ files, handleFileSelect, showHiddenFiles }) => { const FileTree: React.FC<FileTreeProps> = ({
const target = useRef(null); files,
handleFileSelect,
showHiddenFiles,
}) => {
const target = useRef<HTMLDivElement>(null);
const size = useSize(target); const size = useSize(target);
files = files.filter((file) => { const filteredFiles = files.filter((file) => {
if (file.name.startsWith('.') && !showHiddenFiles) { if (file.name.startsWith('.') && !showHiddenFiles) {
return false; return false;
} }
@@ -83,22 +109,27 @@ const FileTree = ({ files, handleFileSelect, showHiddenFiles }) => {
> >
{size && ( {size && (
<Tree <Tree
data={files} data={filteredFiles}
openByDefault={false} openByDefault={false}
width={size.width} width={size.width}
height={size.height} height={size.height}
indent={24} indent={24}
rowHeight={28} rowHeight={28}
onActivate={(node) => { onActivate={(node) => {
const fileNode = node.data as FileNode;
if (!node.isInternal) { if (!node.isInternal) {
handleFileSelect(node.data.path); handleFileSelect(fileNode.path);
} }
}} }}
onNodeClick={(node) => { {...({
// Use a spread with type assertion to add onNodeClick
onNodeClick: (node: NodeApi<FileNode>) => {
const fileNode = node.data as FileNode;
if (!node.isInternal) { if (!node.isInternal) {
handleFileSelect(node.data.path); handleFileSelect(fileNode.path);
} }
}} },
} as any)}
> >
{Node} {Node}
</Tree> </Tree>