From 33b0ea4c4adb726272ae8d1be112404b43663c26 Mon Sep 17 00:00:00 2001 From: simosmik Date: Mon, 16 Feb 2026 14:02:18 +0000 Subject: [PATCH] feature: swap default code editor to sidebar and make the modal optional --- src/components/CodeEditor.jsx | 86 ++++++++++--------- src/components/FileTree.jsx | 22 +---- src/components/main-content/types/types.ts | 1 + .../main-content/view/MainContent.tsx | 5 +- .../view/subcomponents/EditorSidebar.tsx | 18 +++- 5 files changed, 68 insertions(+), 64 deletions(-) diff --git a/src/components/CodeEditor.jsx b/src/components/CodeEditor.jsx index 9b235bb..ee2249d 100644 --- a/src/components/CodeEditor.jsx +++ b/src/components/CodeEditor.jsx @@ -143,7 +143,7 @@ function MarkdownPreview({ content }) { ); } -function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded = false, onToggleExpand = null }) { +function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded = false, onToggleExpand = null, onPopOut = null }) { const { t } = useTranslation('codeEditor'); const [content, setContent] = useState(''); const [loading, setLoading] = useState(true); @@ -165,7 +165,7 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded return localStorage.getItem('codeEditorLineNumbers') !== 'false'; }); const [fontSize, setFontSize] = useState(() => { - return localStorage.getItem('codeEditorFontSize') || '14'; + return localStorage.getItem('codeEditorFontSize') || '12'; }); const [markdownPreview, setMarkdownPreview] = useState(false); const editorRef = useRef(null); @@ -304,6 +304,16 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded `; + if (isSidebar && onPopOut) { + toolbarHTML += ` + + `; + } + // Expand button (only in sidebar mode) if (isSidebar && onToggleExpand) { toolbarHTML += ` @@ -323,7 +333,6 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded dom.innerHTML = toolbarHTML; - // Attach event listeners for diff navigation if (hasDiff) { const prevBtn = dom.querySelector('.cm-diff-nav-prev'); const nextBtn = dom.querySelector('.cm-diff-nav-next'); @@ -355,7 +364,6 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded }); } - // Attach event listener for toggle diff button if (file.diffInfo) { const toggleDiffBtn = dom.querySelector('.cm-toggle-diff-btn'); toggleDiffBtn?.addEventListener('click', () => { @@ -363,7 +371,6 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded }); } - // Attach event listener for settings button const settingsBtn = dom.querySelector('.cm-settings-btn'); settingsBtn?.addEventListener('click', () => { if (window.openSettings) { @@ -371,7 +378,13 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded } }); - // Attach event listener for expand button + if (isSidebar && onPopOut) { + const popoutBtn = dom.querySelector('.cm-popout-btn'); + popoutBtn?.addEventListener('click', () => { + onPopOut(); + }); + } + if (isSidebar && onToggleExpand) { const expandBtn = dom.querySelector('.cm-expand-btn'); expandBtn?.addEventListener('click', () => { @@ -390,7 +403,7 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded }; return [showPanel.of(createPanel)]; - }, [file.diffInfo, showDiff, isSidebar, isExpanded, onToggleExpand]); + }, [file.diffInfo, showDiff, isSidebar, isExpanded, onToggleExpand, onPopOut]); // Get language extension based on file extension const getLanguageExtension = (filename) => { @@ -666,16 +679,16 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded /* Editor toolbar panel styling */ .cm-editor-toolbar-panel { - padding: 8px 12px; + padding: 4px 10px; background-color: ${isDarkMode ? '#1f2937' : '#ffffff'}; border-bottom: 1px solid ${isDarkMode ? '#374151' : '#e5e7eb'}; color: ${isDarkMode ? '#d1d5db' : '#374151'}; - font-size: 14px; + font-size: 12px; } .cm-diff-nav-btn, .cm-toolbar-btn { - padding: 4px; + padding: 3px; background: transparent; border: none; cursor: pointer; @@ -712,72 +725,67 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded (isFullscreen ? ' md:w-full md:h-full md:rounded-none' : ' md:w-full md:max-w-6xl md:h-[80vh] md:max-h-[80vh]') }`}> {/* Header */} -
-
+
+
-

{file.name}

+

{file.name}

{file.diffInfo && ( - + {t('header.showingChanges')} )}
-

{file.path}

+

{file.path}

-
+
{isMarkdownFile && ( )} {!isSidebar && (
@@ -851,13 +859,13 @@ function CodeEditor({ file, onClose, projectPath, isSidebar = false, isExpanded
{/* Footer */} -
-
+
+
{t('footer.lines')} {content.split('\n').length} {t('footer.characters')} {content.length}
-
+
{t('footer.shortcuts')}
diff --git a/src/components/FileTree.jsx b/src/components/FileTree.jsx index e034b98..661683e 100644 --- a/src/components/FileTree.jsx +++ b/src/components/FileTree.jsx @@ -13,7 +13,6 @@ import { Scroll, FlaskConical, NotebookPen, FileCheck, Workflow, Blocks } from 'lucide-react'; import { cn } from '../lib/utils'; -import CodeEditor from './CodeEditor'; import ImageViewer from './ImageViewer'; import { api } from '../utils/api'; @@ -260,12 +259,11 @@ function getFileIconData(filename) { // ─── Component ─────────────────────────────────────────────────────── -function FileTree({ selectedProject }) { +function FileTree({ selectedProject, onFileOpen }) { const { t } = useTranslation(); const [files, setFiles] = useState([]); const [loading, setLoading] = useState(false); const [expandedDirs, setExpandedDirs] = useState(new Set()); - const [selectedFile, setSelectedFile] = useState(null); const [selectedImage, setSelectedImage] = useState(null); const [viewMode, setViewMode] = useState('detailed'); const [searchQuery, setSearchQuery] = useState(''); @@ -403,13 +401,8 @@ function FileTree({ selectedProject }) { projectPath: selectedProject.path, projectName: selectedProject.name }); - } else { - setSelectedFile({ - name: item.name, - path: item.path, - projectPath: selectedProject.path, - projectName: selectedProject.name - }); + } else if (onFileOpen) { + onFileOpen(item.path); } }; @@ -722,15 +715,6 @@ function FileTree({ selectedProject }) { )} - {/* Code Editor Modal */} - {selectedFile && ( - setSelectedFile(null)} - projectPath={selectedFile.projectPath} - /> - )} - {/* Image Viewer Modal */} {selectedImage && ( void; onToggleEditorExpand: () => void; projectPath?: string; + fillSpace?: boolean; } export interface TaskMasterPanelProps { diff --git a/src/components/main-content/view/MainContent.tsx b/src/components/main-content/view/MainContent.tsx index 1db3315..1279436 100644 --- a/src/components/main-content/view/MainContent.tsx +++ b/src/components/main-content/view/MainContent.tsx @@ -109,7 +109,7 @@ function MainContent({ />
-
+
- +
)} @@ -172,6 +172,7 @@ function MainContent({ onCloseEditor={handleCloseEditor} onToggleEditorExpand={handleToggleEditorExpand} projectPath={selectedProject.path} + fillSpace={activeTab === 'files'} />
diff --git a/src/components/main-content/view/subcomponents/EditorSidebar.tsx b/src/components/main-content/view/subcomponents/EditorSidebar.tsx index 591a3b8..ea6cf70 100644 --- a/src/components/main-content/view/subcomponents/EditorSidebar.tsx +++ b/src/components/main-content/view/subcomponents/EditorSidebar.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import CodeEditor from '../../../CodeEditor'; import type { EditorSidebarProps } from '../../types/types'; @@ -13,22 +14,30 @@ export default function EditorSidebar({ onCloseEditor, onToggleEditorExpand, projectPath, + fillSpace, }: EditorSidebarProps) { + const [poppedOut, setPoppedOut] = useState(false); + if (!editingFile) { return null; } - if (isMobile) { + if (isMobile || poppedOut) { return ( { + setPoppedOut(false); + onCloseEditor(); + }} projectPath={projectPath} isSidebar={false} /> ); } + const useFlex = editorExpanded || fillSpace; + return ( <> {!editorExpanded && ( @@ -43,8 +52,8 @@ export default function EditorSidebar({ )}
setPoppedOut(true)} />