Remove FileList, FileOps and GitOps contexts

This commit is contained in:
2024-10-05 12:12:51 +02:00
parent 96e0d1b73d
commit 5ea932c96e
13 changed files with 114 additions and 148 deletions

View File

@@ -1,14 +1,10 @@
// App.js
import React from 'react'; import React from 'react';
import { GeistProvider, CssBaseline, Page } from '@geist-ui/core'; import { GeistProvider, CssBaseline, Page } from '@geist-ui/core';
import Header from './components/Header'; import Header from './components/Header';
import MainContent from './components/MainContent'; import MainContent from './components/MainContent';
import { SettingsProvider, useSettings } from './contexts/SettingsContext'; import { SettingsProvider, useSettings } from './contexts/SettingsContext';
import { ModalProvider } from './contexts/ModalContext'; import { ModalProvider } from './contexts/ModalContext';
import { GitOperationsProvider } from './contexts/GitOperationsContext';
import { FileListProvider } from './contexts/FileListContext';
import { FileSelectionProvider } from './contexts/FileSelectionContext'; import { FileSelectionProvider } from './contexts/FileSelectionContext';
import { FileOperationsProvider } from './contexts/FileOperationsContext';
import { EditorContentProvider } from './contexts/EditorContentContext'; import { EditorContentProvider } from './contexts/EditorContentContext';
import { FileManagementProvider } from './contexts/FileManagementContext'; import { FileManagementProvider } from './contexts/FileManagementContext';
import './App.scss'; import './App.scss';
@@ -37,19 +33,13 @@ function App() {
return ( return (
<SettingsProvider> <SettingsProvider>
<ModalProvider> <ModalProvider>
<GitOperationsProvider> <FileManagementProvider>
<FileListProvider> <FileSelectionProvider>
<FileManagementProvider> <EditorContentProvider>
<FileSelectionProvider> <AppContent />
<FileOperationsProvider> </EditorContentProvider>
<EditorContentProvider> </FileSelectionProvider>
<AppContent /> </FileManagementProvider>
</EditorContentProvider>
</FileOperationsProvider>
</FileSelectionProvider>
</FileManagementProvider>
</FileListProvider>
</GitOperationsProvider>
</ModalProvider> </ModalProvider>
</SettingsProvider> </SettingsProvider>
); );

View File

@@ -1,14 +1,17 @@
import React from 'react'; import React from 'react';
import { Button, Tooltip, ButtonGroup, Spacer } from '@geist-ui/core'; import { Button, Tooltip, ButtonGroup, Spacer } from '@geist-ui/core';
import { Plus, Trash, GitPullRequest, GitCommit } from '@geist-ui/icons'; import { Plus, Trash, GitPullRequest, GitCommit } from '@geist-ui/icons';
import { useGitOperationsContext } from '../contexts/GitOperationsContext';
import { useSettings } from '../contexts/SettingsContext'; import { useSettings } from '../contexts/SettingsContext';
import { useFileSelection } from '../contexts/FileSelectionContext'; import { useFileSelection } from '../contexts/FileSelectionContext';
import { useModalContext } from '../contexts/ModalContext'; import { useModalContext } from '../contexts/ModalContext';
const FileActions = () => { const FileActions = ({
onCreateFile,
onDeleteFile,
onPullChanges,
onCommitAndPush,
}) => {
const { selectedFile } = useFileSelection(); const { selectedFile } = useFileSelection();
const { pullLatestChanges } = useGitOperationsContext();
const { settings } = useSettings(); const { settings } = useSettings();
const { const {
setNewFileModalVisible, setNewFileModalVisible,
@@ -59,7 +62,7 @@ const FileActions = () => {
icon={<GitPullRequest />} icon={<GitPullRequest />}
auto auto
scale={2 / 3} scale={2 / 3}
onClick={pullLatestChanges} onClick={onPullChanges}
disabled={!settings.gitEnabled} disabled={!settings.gitEnabled}
px={0.6} px={0.6}
/> />

View File

@@ -1,12 +1,10 @@
import React from 'react'; import React from 'react';
import { Tree } from '@geist-ui/core'; import { Tree } from '@geist-ui/core';
import { File, Folder, Image } from '@geist-ui/icons'; import { File, Folder, Image } from '@geist-ui/icons';
import { useFileListContext } from '../contexts/FileListContext';
import { isImageFile } from '../utils/fileHelpers'; import { isImageFile } from '../utils/fileHelpers';
import { useFileSelection } from '../contexts/FileSelectionContext'; import { useFileSelection } from '../contexts/FileSelectionContext';
const FileTree = () => { const FileTree = ({ files }) => {
const { files } = useFileListContext();
const { selectedFile, handleFileSelect } = useFileSelection(); const { selectedFile, handleFileSelect } = useFileSelection();
if (files.length === 0) { if (files.length === 0) {

View File

@@ -1,24 +1,91 @@
import React, { useState } from 'react';
import { Grid, Breadcrumbs, Tabs, Dot } from '@geist-ui/core';
import { Code, Eye } from '@geist-ui/icons';
import FileTree from './FileTree';
import FileActions from './FileActions'; import FileActions from './FileActions';
import FileTree from './FileTree';
import ContentView from './ContentView'; import ContentView from './ContentView';
import CreateFileModal from './modals/CreateFileModal'; import CreateFileModal from './modals/CreateFileModal';
import DeleteFileModal from './modals/DeleteFileModal'; import DeleteFileModal from './modals/DeleteFileModal';
import CommitMessageModal from './modals/CommitMessageModal'; import CommitMessageModal from './modals/CommitMessageModal';
import { useEditorContent } from '../contexts/EditorContentContext'; import { useEditorContent } from '../contexts/EditorContentContext';
import { useFileSelection } from '../contexts/FileSelectionContext'; import { useFileSelection } from '../contexts/FileSelectionContext';
import { useSettings } from '../contexts/SettingsContext';
import { useFileOperations } from '../hooks/useFileOperations';
import { pullChanges, commitAndPush, fetchFileList } from '../services/api';
import { Breadcrumbs, Grid, Tabs, useToasts } from '@geist-ui/core';
import { Code, Eye } from '@geist-ui/icons';
import { useState, useCallback, useEffect } from 'react';
import React from 'react';
const MainContent = () => { const MainContent = () => {
const [activeTab, setActiveTab] = useState('source'); const [activeTab, setActiveTab] = useState('source');
const [files, setFiles] = useState([]);
const { hasUnsavedChanges } = useEditorContent(); const { hasUnsavedChanges } = useEditorContent();
const { selectedFile } = useFileSelection(); const { selectedFile } = useFileSelection();
const { settings } = useSettings();
const { handleCreate, handleDelete } = useFileOperations();
const { setToast } = useToasts();
const refreshFileList = useCallback(async () => {
try {
const fileList = await fetchFileList();
setFiles(fileList);
} catch (error) {
console.error('Failed to fetch file list:', error);
setToast({ text: 'Failed to refresh file list', type: 'error' });
}
}, [setToast]);
useEffect(() => {
refreshFileList();
}, []);
const handleTabChange = (value) => { const handleTabChange = (value) => {
setActiveTab(value); setActiveTab(value);
}; };
const pullLatestChanges = useCallback(async () => {
if (!settings.gitEnabled) return;
try {
await pullChanges();
await refreshFileList();
setToast({ text: 'Successfully pulled latest changes', type: 'success' });
} catch (error) {
console.error('Failed to pull latest changes:', error);
setToast({ text: 'Failed to pull latest changes', type: 'error' });
}
}, [settings.gitEnabled, setToast, refreshFileList]);
const handleCommitAndPush = useCallback(
async (message) => {
if (!settings.gitEnabled) return;
try {
await commitAndPush(message);
setToast({
text: 'Successfully committed and pushed changes',
type: 'success',
});
} catch (error) {
console.error('Failed to commit and push changes:', error);
setToast({ text: 'Failed to commit and push changes', type: 'error' });
}
},
[settings.gitEnabled, setToast]
);
const handleCreateFile = useCallback(
async (fileName) => {
await handleCreate(fileName);
await refreshFileList();
},
[handleCreate, refreshFileList]
);
const handleDeleteFile = useCallback(
async (filePath) => {
await handleDelete(filePath);
await refreshFileList();
},
[handleDelete, refreshFileList]
);
const renderBreadcrumbs = () => { const renderBreadcrumbs = () => {
if (!selectedFile) return <div className="breadcrumbs-container"></div>; if (!selectedFile) return <div className="breadcrumbs-container"></div>;
const pathParts = selectedFile.split('/'); const pathParts = selectedFile.split('/');
@@ -41,8 +108,13 @@ const MainContent = () => {
<Grid.Container gap={1} height="calc(100vh - 64px)"> <Grid.Container gap={1} height="calc(100vh - 64px)">
<Grid xs={24} sm={6} md={5} lg={4} height="100%" className="sidebar"> <Grid xs={24} sm={6} md={5} lg={4} height="100%" className="sidebar">
<div className="file-tree-container"> <div className="file-tree-container">
<FileActions /> <FileActions
<FileTree /> onCreateFile={handleCreateFile}
onDeleteFile={handleDeleteFile}
onPullChanges={pullLatestChanges}
onCommitAndPush={handleCommitAndPush}
/>
<FileTree files={files} />
</div> </div>
</Grid> </Grid>
<Grid <Grid
@@ -65,9 +137,9 @@ const MainContent = () => {
</div> </div>
</Grid> </Grid>
</Grid.Container> </Grid.Container>
<CreateFileModal /> <CreateFileModal onCreateFile={handleCreateFile} />
<DeleteFileModal /> <DeleteFileModal onDeleteFile={handleDeleteFile} />
<CommitMessageModal /> <CommitMessageModal onCommitAndPush={handleCommitAndPush} />
</> </>
); );
}; };

View File

@@ -1,17 +1,15 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Modal, Input } from '@geist-ui/core'; import { Modal, Input } from '@geist-ui/core';
import { useGitOperationsContext } from '../../contexts/GitOperationsContext';
import { useModalContext } from '../../contexts/ModalContext'; import { useModalContext } from '../../contexts/ModalContext';
const CommitMessageModal = () => { const CommitMessageModal = ({ onCommitAndPush }) => {
const [message, setMessage] = useState(''); const [message, setMessage] = useState('');
const { handleCommitAndPush } = useGitOperationsContext();
const { commitMessageModalVisible, setCommitMessageModalVisible } = const { commitMessageModalVisible, setCommitMessageModalVisible } =
useModalContext(); useModalContext();
const handleSubmit = async () => { const handleSubmit = async () => {
if (message) { if (message) {
await handleCommitAndPush(message); await onCommitAndPush(message);
setMessage(''); setMessage('');
setCommitMessageModalVisible(false); setCommitMessageModalVisible(false);
} }

View File

@@ -1,16 +1,14 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Modal, Input } from '@geist-ui/core'; import { Modal, Input } from '@geist-ui/core';
import { useFileOperations } from '../../contexts/FileOperationsContext';
import { useModalContext } from '../../contexts/ModalContext'; import { useModalContext } from '../../contexts/ModalContext';
const CreateFileModal = () => { const CreateFileModal = ({ onCreateFile }) => {
const [fileName, setFileName] = useState(''); const [fileName, setFileName] = useState('');
const { newFileModalVisible, setNewFileModalVisible } = useModalContext(); const { newFileModalVisible, setNewFileModalVisible } = useModalContext();
const { handleCreateNewFile } = useFileOperations();
const handleSubmit = async () => { const handleSubmit = async () => {
if (fileName) { if (fileName) {
await handleCreateNewFile(fileName); await onCreateFile(fileName);
setFileName(''); setFileName('');
setNewFileModalVisible(false); setNewFileModalVisible(false);
} }

View File

@@ -3,13 +3,13 @@ import { Modal, Text } from '@geist-ui/core';
import { useModalContext } from '../../contexts/ModalContext'; import { useModalContext } from '../../contexts/ModalContext';
import { useFileSelection } from '../../contexts/FileSelectionContext'; import { useFileSelection } from '../../contexts/FileSelectionContext';
const DeleteFileModal = () => { const DeleteFileModal = ({ onDeleteFile }) => {
const { selectedFile, handleDeleteFile } = useFileSelection(); const { selectedFile } = useFileSelection();
const { deleteFileModalVisible, setDeleteFileModalVisible } = const { deleteFileModalVisible, setDeleteFileModalVisible } =
useModalContext(); useModalContext();
const handleConfirm = async () => { const handleConfirm = async () => {
await handleDeleteFile(); await onDeleteFile(selectedFile);
setDeleteFileModalVisible(false); setDeleteFileModalVisible(false);
}; };

View File

@@ -1,26 +0,0 @@
import React, { createContext, useContext, useMemo } from 'react';
import { useFileList } from '../hooks/useFileList';
const FileListContext = createContext();
export const FileListProvider = ({ children }) => {
const { files, loadFileList } = useFileList();
const value = useMemo(() => ({ files, loadFileList }), [files, loadFileList]);
return (
<FileListContext.Provider value={value}>
{children}
</FileListContext.Provider>
);
};
export const useFileListContext = () => {
const context = useContext(FileListContext);
if (context === undefined) {
throw new Error(
'useFileListContext must be used within a FileListProvider'
);
}
return context;
};

View File

@@ -1,32 +0,0 @@
import React, { createContext, useContext, useMemo } from 'react';
import { useFileContent } from '../hooks/useFileContent';
const FileOperationsContext = createContext();
export const FileOperationsProvider = ({ children }) => {
const { handleCreateNewFile, handleDeleteFile } = useFileContent();
const value = useMemo(
() => ({
handleCreateNewFile,
handleDeleteFile,
}),
[handleCreateNewFile, handleDeleteFile]
);
return (
<FileOperationsContext.Provider value={value}>
{children}
</FileOperationsContext.Provider>
);
};
export const useFileOperations = () => {
const context = useContext(FileOperationsContext);
if (context === undefined) {
throw new Error(
'useFileOperations must be used within a FileOperationsProvider'
);
}
return context;
};

View File

@@ -1,24 +0,0 @@
import React, { createContext, useContext } from 'react';
import { useGitOperations } from '../hooks/useGitOperations';
const GitOperationsContext = createContext();
export const GitOperationsProvider = ({ children }) => {
const gitOperationsHook = useGitOperations();
return (
<GitOperationsContext.Provider value={gitOperationsHook}>
{children}
</GitOperationsContext.Provider>
);
};
export const useGitOperationsContext = () => {
const context = useContext(GitOperationsContext);
if (!context) {
throw new Error(
'useGitOperationsContext must be used within a GitOperationsProvider'
);
}
return context;
};

View File

@@ -1,7 +1,6 @@
import { useEffect, useCallback } from 'react'; import { useEffect, useCallback } from 'react';
import { useFileSelection } from './useFileSelection'; import { useFileSelection } from './useFileSelection';
import { useFileContent } from './useFileContent'; import { useFileContent } from './useFileContent';
import { useFileOperations } from './useFileOperations';
export const useFileManagement = () => { export const useFileManagement = () => {
const { selectedFile, isNewFile, handleFileSelect } = useFileSelection(); const { selectedFile, isNewFile, handleFileSelect } = useFileSelection();
@@ -12,10 +11,7 @@ export const useFileManagement = () => {
hasUnsavedChanges, hasUnsavedChanges,
loadFileContent, loadFileContent,
handleContentChange, handleContentChange,
setHasUnsavedChanges,
} = useFileContent(); } = useFileContent();
const { handleSave, handleDelete, handleCreateNewFile } =
useFileOperations(setHasUnsavedChanges);
useEffect(() => { useEffect(() => {
if (selectedFile) { if (selectedFile) {
@@ -40,8 +36,5 @@ export const useFileManagement = () => {
hasUnsavedChanges, hasUnsavedChanges,
handleFileSelect: handleFileSelectAndLoad, handleFileSelect: handleFileSelectAndLoad,
handleContentChange, handleContentChange,
handleSave: (filePath) => handleSave(filePath, content),
handleDelete,
handleCreateNewFile,
}; };
}; };

View File

@@ -16,7 +16,6 @@ export const useFileNavigation = () => {
handleFileSelect(filePaths[0]); handleFileSelect(filePaths[0]);
} else if (filePaths.length > 1) { } else if (filePaths.length > 1) {
// Handle multiple file options (you may want to show a modal or dropdown) // Handle multiple file options (you may want to show a modal or dropdown)
console.log('Multiple files found:', filePaths);
setToast({ setToast({
text: 'Multiple files found with the same name. Please specify the full path.', text: 'Multiple files found with the same name. Please specify the full path.',
type: 'warning', type: 'warning',

View File

@@ -32,19 +32,16 @@ export const useFileOperations = (setHasUnsavedChanges) => {
} }
}, []); }, []);
const handleCreateNewFile = useCallback( const handleCreate = useCallback(async (fileName, initialContent = '') => {
async (fileName, initialContent = '') => { try {
try { await saveFileContent(fileName, initialContent);
await saveFileContent(fileName, initialContent); return true;
return true; } catch (error) {
} catch (error) { setToast({ text: `Error creating new file`, type: 'error' });
setToast({ text: `Error creating new file`, type: 'error' }); console.error('Error creating new file:', error);
console.error('Error creating new file:', error); return false;
return false; }
} }, []);
},
[]
);
return { handleSave, handleDelete, handleCreateNewFile }; return { handleSave, handleDelete, handleCreate };
}; };