diff --git a/frontend/src/App.js b/frontend/src/App.js index c34bdbe..77cd36c 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -1,94 +1,39 @@ -import React, { useState, useEffect } from 'react'; -import { GeistProvider, CssBaseline, Page, useToasts } from '@geist-ui/core'; +import React from 'react'; +import { GeistProvider, CssBaseline, Page } from '@geist-ui/core'; import Header from './components/Header'; import MainContent from './components/MainContent'; -import useFileManagement from './hooks/useFileManagement'; -import { fetchUserSettings } from './services/api'; +import { SettingsProvider, useSettings } from './contexts/SettingsContext'; +import { ModalProvider } from './contexts/ModalContext'; import './App.scss'; -function App() { - const [themeType, setThemeType] = useState('light'); - const [userId, setUserId] = useState(1); - const [settings, setSettings] = useState({ gitEnabled: false }); - const { setToast } = useToasts(); +function AppContent() { + const { settings, loading } = useSettings(); - useEffect(() => { - const loadUserSettings = async () => { - try { - const fetchedSettings = await fetchUserSettings(userId); - setSettings(fetchedSettings.settings); - setThemeType(fetchedSettings.settings.theme); - } catch (error) { - console.error('Failed to load user settings:', error); - } - }; - - loadUserSettings(); - }, [userId]); - - const { - content, - files, - selectedFile, - isNewFile, - hasUnsavedChanges, - error, - handleFileSelect, - handleContentChange, - handleSave, - pullLatestChanges, - lookupFileByName, - } = useFileManagement(settings.gitEnabled); - - const handleThemeChange = (newTheme) => { - setThemeType(newTheme); - }; - - const handleLinkClick = async (filename) => { - try { - const filePaths = await lookupFileByName(filename); - if (filePaths.length === 1) { - handleFileSelect(filePaths[0]); - } else if (filePaths.length > 1) { - setFileOptions(filePaths.map((path) => ({ label: path, value: path }))); - setFileSelectionModalVisible(true); - } else { - setToast({ text: `File "${filename}" not found`, type: 'error' }); - } - } catch (error) { - console.error('Error looking up file:', error); - setToast({ - text: 'Failed to lookup file. Please try again.', - type: 'error', - }); - } - }; + if (loading) { + return
Loading...
; + } return ( - + -
+
- + ); } +function App() { + return ( + + + + + + ); +} + export default App; diff --git a/frontend/src/components/ContentView.js b/frontend/src/components/ContentView.js index 29aa61e..833c74b 100644 --- a/frontend/src/components/ContentView.js +++ b/frontend/src/components/ContentView.js @@ -1,19 +1,33 @@ import React from 'react'; import Editor from './Editor'; import MarkdownPreview from './MarkdownPreview'; +import { Text } from '@geist-ui/core'; import { getFileUrl } from '../services/api'; import { isImageFile } from '../utils/fileHelpers'; const ContentView = ({ activeTab, - content, selectedFile, - onContentChange, - onSave, - themeType, - onLinkClick, - lookupFileByName, + content, + handleContentChange, + handleSave, + handleLinkClick, }) => { + if (!selectedFile) { + return ( +
+ No file selected. +
+ ); + } + if (isImageFile(selectedFile)) { return (
@@ -33,18 +47,12 @@ const ContentView = ({ return activeTab === 'source' ? ( ) : ( - + ); }; diff --git a/frontend/src/components/Editor.js b/frontend/src/components/Editor.js index 4b7ee76..1491f8e 100644 --- a/frontend/src/components/Editor.js +++ b/frontend/src/components/Editor.js @@ -5,14 +5,16 @@ import { EditorView, keymap } from '@codemirror/view'; import { markdown } from '@codemirror/lang-markdown'; import { defaultKeymap } from '@codemirror/commands'; import { oneDark } from '@codemirror/theme-one-dark'; +import { useSettings } from '../contexts/SettingsContext'; -const Editor = ({ content, onChange, onSave, filePath, themeType }) => { +const Editor = ({ content, handleContentChange, handleSave, selectedFile }) => { + const { settings } = useSettings(); const editorRef = useRef(); const viewRef = useRef(); useEffect(() => { - const handleSave = (view) => { - onSave(filePath, view.state.doc.toString()); + const handleEditorSave = (view) => { + handleSave(selectedFile, view.state.doc.toString()); return true; }; @@ -25,12 +27,12 @@ const Editor = ({ content, onChange, onSave, filePath, themeType }) => { overflow: 'auto', }, '.cm-gutters': { - backgroundColor: themeType === 'dark' ? '#1e1e1e' : '#f5f5f5', - color: themeType === 'dark' ? '#858585' : '#999', + backgroundColor: settings.theme === 'dark' ? '#1e1e1e' : '#f5f5f5', + color: settings.theme === 'dark' ? '#858585' : '#999', border: 'none', }, '.cm-activeLineGutter': { - backgroundColor: themeType === 'dark' ? '#2c313a' : '#e8e8e8', + backgroundColor: settings.theme === 'dark' ? '#2c313a' : '#e8e8e8', }, }); @@ -44,17 +46,17 @@ const Editor = ({ content, onChange, onSave, filePath, themeType }) => { keymap.of([ { key: 'Ctrl-s', - run: handleSave, + run: handleEditorSave, preventDefault: true, }, ]), EditorView.updateListener.of((update) => { if (update.docChanged) { - onChange(update.state.doc.toString()); + handleContentChange(update.state.doc.toString()); } }), theme, - themeType === 'dark' ? oneDark : [], + settings.theme === 'dark' ? oneDark : [], ], }); @@ -68,7 +70,7 @@ const Editor = ({ content, onChange, onSave, filePath, themeType }) => { return () => { view.destroy(); }; - }, [filePath, themeType]); + }, [settings.theme, handleContentChange]); useEffect(() => { if (viewRef.current && content !== viewRef.current.state.doc.toString()) { diff --git a/frontend/src/components/FileActions.js b/frontend/src/components/FileActions.js index 6a54f46..78eaf4b 100644 --- a/frontend/src/components/FileActions.js +++ b/frontend/src/components/FileActions.js @@ -1,16 +1,21 @@ import React from 'react'; import { Button, Tooltip, ButtonGroup, Spacer } from '@geist-ui/core'; import { Plus, Trash, GitPullRequest, GitCommit } from '@geist-ui/icons'; +import { useSettings } from '../contexts/SettingsContext'; +import { useModalContext } from '../contexts/ModalContext'; + +const FileActions = ({ handlePullChanges, selectedFile }) => { + const { settings } = useSettings(); + const { + setNewFileModalVisible, + setDeleteFileModalVisible, + setCommitMessageModalVisible, + } = useModalContext(); + + const handleCreateFile = () => setNewFileModalVisible(true); + const handleDeleteFile = () => setDeleteFileModalVisible(true); + const handleCommitAndPush = () => setCommitMessageModalVisible(true); -const FileActions = ({ - selectedFile, - gitEnabled, - gitAutoCommit, - onPull, - onCommitAndPush, - onCreateFile, - onDeleteFile, -}) => { return ( @@ -18,7 +23,7 @@ const FileActions = ({ icon={} auto scale={2 / 3} - onClick={onCreateFile} + onClick={handleCreateFile} px={0.6} /> @@ -31,7 +36,7 @@ const FileActions = ({ icon={} auto scale={2 / 3} - onClick={onDeleteFile} + onClick={handleDeleteFile} disabled={!selectedFile} type="error" px={0.6} @@ -39,24 +44,28 @@ const FileActions = ({