diff --git a/frontend/src/App.js b/frontend/src/App.js index 606643f..231af29 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,14 +1,10 @@ -// App.js import React from 'react'; import { GeistProvider, CssBaseline, Page } from '@geist-ui/core'; import Header from './components/Header'; import MainContent from './components/MainContent'; import { SettingsProvider, useSettings } from './contexts/SettingsContext'; import { ModalProvider } from './contexts/ModalContext'; -import { GitOperationsProvider } from './contexts/GitOperationsContext'; -import { FileListProvider } from './contexts/FileListContext'; import { FileSelectionProvider } from './contexts/FileSelectionContext'; -import { FileOperationsProvider } from './contexts/FileOperationsContext'; import { EditorContentProvider } from './contexts/EditorContentContext'; import { FileManagementProvider } from './contexts/FileManagementContext'; import './App.scss'; @@ -37,19 +33,13 @@ function App() { return ( - - - - - - - - - - - - - + + + + + + + ); diff --git a/frontend/src/components/FileActions.js b/frontend/src/components/FileActions.js index 24e106d..70ffda3 100644 --- a/frontend/src/components/FileActions.js +++ b/frontend/src/components/FileActions.js @@ -1,14 +1,17 @@ import React from 'react'; import { Button, Tooltip, ButtonGroup, Spacer } from '@geist-ui/core'; import { Plus, Trash, GitPullRequest, GitCommit } from '@geist-ui/icons'; -import { useGitOperationsContext } from '../contexts/GitOperationsContext'; import { useSettings } from '../contexts/SettingsContext'; import { useFileSelection } from '../contexts/FileSelectionContext'; import { useModalContext } from '../contexts/ModalContext'; -const FileActions = () => { +const FileActions = ({ + onCreateFile, + onDeleteFile, + onPullChanges, + onCommitAndPush, +}) => { const { selectedFile } = useFileSelection(); - const { pullLatestChanges } = useGitOperationsContext(); const { settings } = useSettings(); const { setNewFileModalVisible, @@ -59,7 +62,7 @@ const FileActions = () => { icon={} auto scale={2 / 3} - onClick={pullLatestChanges} + onClick={onPullChanges} disabled={!settings.gitEnabled} px={0.6} /> diff --git a/frontend/src/components/FileTree.js b/frontend/src/components/FileTree.js index 844b560..ac8dd85 100644 --- a/frontend/src/components/FileTree.js +++ b/frontend/src/components/FileTree.js @@ -1,12 +1,10 @@ import React from 'react'; import { Tree } from '@geist-ui/core'; import { File, Folder, Image } from '@geist-ui/icons'; -import { useFileListContext } from '../contexts/FileListContext'; import { isImageFile } from '../utils/fileHelpers'; import { useFileSelection } from '../contexts/FileSelectionContext'; -const FileTree = () => { - const { files } = useFileListContext(); +const FileTree = ({ files }) => { const { selectedFile, handleFileSelect } = useFileSelection(); if (files.length === 0) { diff --git a/frontend/src/components/MainContent.js b/frontend/src/components/MainContent.js index cdbfe38..f84306e 100644 --- a/frontend/src/components/MainContent.js +++ b/frontend/src/components/MainContent.js @@ -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 FileTree from './FileTree'; import ContentView from './ContentView'; import CreateFileModal from './modals/CreateFileModal'; import DeleteFileModal from './modals/DeleteFileModal'; import CommitMessageModal from './modals/CommitMessageModal'; import { useEditorContent } from '../contexts/EditorContentContext'; 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 [activeTab, setActiveTab] = useState('source'); + const [files, setFiles] = useState([]); const { hasUnsavedChanges } = useEditorContent(); 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) => { 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 = () => { if (!selectedFile) return
; const pathParts = selectedFile.split('/'); @@ -41,8 +108,13 @@ const MainContent = () => {
- - + +
{
- - - + + + ); }; diff --git a/frontend/src/components/modals/CommitMessageModal.js b/frontend/src/components/modals/CommitMessageModal.js index faf3cb8..b2a6720 100644 --- a/frontend/src/components/modals/CommitMessageModal.js +++ b/frontend/src/components/modals/CommitMessageModal.js @@ -1,17 +1,15 @@ import React, { useState } from 'react'; import { Modal, Input } from '@geist-ui/core'; -import { useGitOperationsContext } from '../../contexts/GitOperationsContext'; import { useModalContext } from '../../contexts/ModalContext'; -const CommitMessageModal = () => { +const CommitMessageModal = ({ onCommitAndPush }) => { const [message, setMessage] = useState(''); - const { handleCommitAndPush } = useGitOperationsContext(); const { commitMessageModalVisible, setCommitMessageModalVisible } = useModalContext(); const handleSubmit = async () => { if (message) { - await handleCommitAndPush(message); + await onCommitAndPush(message); setMessage(''); setCommitMessageModalVisible(false); } diff --git a/frontend/src/components/modals/CreateFileModal.js b/frontend/src/components/modals/CreateFileModal.js index ea4b57a..1666dda 100644 --- a/frontend/src/components/modals/CreateFileModal.js +++ b/frontend/src/components/modals/CreateFileModal.js @@ -1,16 +1,14 @@ import React, { useState } from 'react'; import { Modal, Input } from '@geist-ui/core'; -import { useFileOperations } from '../../contexts/FileOperationsContext'; import { useModalContext } from '../../contexts/ModalContext'; -const CreateFileModal = () => { +const CreateFileModal = ({ onCreateFile }) => { const [fileName, setFileName] = useState(''); const { newFileModalVisible, setNewFileModalVisible } = useModalContext(); - const { handleCreateNewFile } = useFileOperations(); const handleSubmit = async () => { if (fileName) { - await handleCreateNewFile(fileName); + await onCreateFile(fileName); setFileName(''); setNewFileModalVisible(false); } diff --git a/frontend/src/components/modals/DeleteFileModal.js b/frontend/src/components/modals/DeleteFileModal.js index 9abf3dd..50714a6 100644 --- a/frontend/src/components/modals/DeleteFileModal.js +++ b/frontend/src/components/modals/DeleteFileModal.js @@ -3,13 +3,13 @@ import { Modal, Text } from '@geist-ui/core'; import { useModalContext } from '../../contexts/ModalContext'; import { useFileSelection } from '../../contexts/FileSelectionContext'; -const DeleteFileModal = () => { - const { selectedFile, handleDeleteFile } = useFileSelection(); +const DeleteFileModal = ({ onDeleteFile }) => { + const { selectedFile } = useFileSelection(); const { deleteFileModalVisible, setDeleteFileModalVisible } = useModalContext(); const handleConfirm = async () => { - await handleDeleteFile(); + await onDeleteFile(selectedFile); setDeleteFileModalVisible(false); }; diff --git a/frontend/src/contexts/FileListContext.js b/frontend/src/contexts/FileListContext.js deleted file mode 100644 index 9192b01..0000000 --- a/frontend/src/contexts/FileListContext.js +++ /dev/null @@ -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 ( - - {children} - - ); -}; - -export const useFileListContext = () => { - const context = useContext(FileListContext); - if (context === undefined) { - throw new Error( - 'useFileListContext must be used within a FileListProvider' - ); - } - return context; -}; diff --git a/frontend/src/contexts/FileOperationsContext.js b/frontend/src/contexts/FileOperationsContext.js deleted file mode 100644 index 41b646b..0000000 --- a/frontend/src/contexts/FileOperationsContext.js +++ /dev/null @@ -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 ( - - {children} - - ); -}; - -export const useFileOperations = () => { - const context = useContext(FileOperationsContext); - if (context === undefined) { - throw new Error( - 'useFileOperations must be used within a FileOperationsProvider' - ); - } - return context; -}; diff --git a/frontend/src/contexts/GitOperationsContext.js b/frontend/src/contexts/GitOperationsContext.js deleted file mode 100644 index 41589c3..0000000 --- a/frontend/src/contexts/GitOperationsContext.js +++ /dev/null @@ -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 ( - - {children} - - ); -}; - -export const useGitOperationsContext = () => { - const context = useContext(GitOperationsContext); - if (!context) { - throw new Error( - 'useGitOperationsContext must be used within a GitOperationsProvider' - ); - } - return context; -}; diff --git a/frontend/src/hooks/useFileManagement.js b/frontend/src/hooks/useFileManagement.js index 8d531dd..7275838 100644 --- a/frontend/src/hooks/useFileManagement.js +++ b/frontend/src/hooks/useFileManagement.js @@ -1,7 +1,6 @@ import { useEffect, useCallback } from 'react'; import { useFileSelection } from './useFileSelection'; import { useFileContent } from './useFileContent'; -import { useFileOperations } from './useFileOperations'; export const useFileManagement = () => { const { selectedFile, isNewFile, handleFileSelect } = useFileSelection(); @@ -12,10 +11,7 @@ export const useFileManagement = () => { hasUnsavedChanges, loadFileContent, handleContentChange, - setHasUnsavedChanges, } = useFileContent(); - const { handleSave, handleDelete, handleCreateNewFile } = - useFileOperations(setHasUnsavedChanges); useEffect(() => { if (selectedFile) { @@ -40,8 +36,5 @@ export const useFileManagement = () => { hasUnsavedChanges, handleFileSelect: handleFileSelectAndLoad, handleContentChange, - handleSave: (filePath) => handleSave(filePath, content), - handleDelete, - handleCreateNewFile, }; }; diff --git a/frontend/src/hooks/useFileNavigation.js b/frontend/src/hooks/useFileNavigation.js index 7d5c239..f5f21ef 100644 --- a/frontend/src/hooks/useFileNavigation.js +++ b/frontend/src/hooks/useFileNavigation.js @@ -16,7 +16,6 @@ export const useFileNavigation = () => { handleFileSelect(filePaths[0]); } else if (filePaths.length > 1) { // Handle multiple file options (you may want to show a modal or dropdown) - console.log('Multiple files found:', filePaths); setToast({ text: 'Multiple files found with the same name. Please specify the full path.', type: 'warning', diff --git a/frontend/src/hooks/useFileOperations.js b/frontend/src/hooks/useFileOperations.js index 18cc0f7..4fb0757 100644 --- a/frontend/src/hooks/useFileOperations.js +++ b/frontend/src/hooks/useFileOperations.js @@ -32,19 +32,16 @@ export const useFileOperations = (setHasUnsavedChanges) => { } }, []); - const handleCreateNewFile = useCallback( - async (fileName, initialContent = '') => { - try { - await saveFileContent(fileName, initialContent); - return true; - } catch (error) { - setToast({ text: `Error creating new file`, type: 'error' }); - console.error('Error creating new file:', error); - return false; - } - }, - [] - ); + const handleCreate = useCallback(async (fileName, initialContent = '') => { + try { + await saveFileContent(fileName, initialContent); + return true; + } catch (error) { + setToast({ text: `Error creating new file`, type: 'error' }); + console.error('Error creating new file:', error); + return false; + } + }, []); - return { handleSave, handleDelete, handleCreateNewFile }; + return { handleSave, handleDelete, handleCreate }; };