mirror of
https://github.com/lordmathis/lemma.git
synced 2025-11-06 07:54:22 +00:00
Migrate file components
This commit is contained in:
@@ -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">
|
||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user