From 7f45540dbe52de2363d085733bef7424e8f2e65e Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Wed, 11 Feb 2026 18:11:06 +0300 Subject: [PATCH] refactor: Restructure files and folders to better mimic feature-based architecture --- src/components/app/AppContent.tsx | 4 +- .../chat/hooks}/useChatComposerState.ts | 12 +- .../chat/hooks}/useChatProviderState.ts | 8 +- .../chat/hooks}/useChatRealtimeHandlers.ts | 8 +- .../chat/hooks}/useChatSessionState.ts | 10 +- .../chat/hooks}/useFileMentions.tsx | 6 +- .../chat/hooks}/useSlashCommands.ts | 6 +- .../{ => chat/view}/ChatInterface.tsx | 20 ++-- .../main-content/hooks}/useEditorSidebar.ts | 4 +- .../hooks}/useMobileMenuHandlers.ts | 0 .../main-content/{ => types}/types.ts | 2 +- .../{ => main-content/view}/MainContent.tsx | 30 ++--- .../subcomponents}/EditorSidebar.tsx | 4 +- .../subcomponents}/MainContentHeader.tsx | 2 +- .../subcomponents}/MainContentStateView.tsx | 2 +- .../subcomponents}/MainContentTabSwitcher.tsx | 4 +- .../subcomponents}/MainContentTitle.tsx | 4 +- .../subcomponents}/MobileMenuButton.tsx | 4 +- .../subcomponents}/TaskMasterPanel.tsx | 14 +-- .../sidebar}/hooks/useSidebarController.ts | 8 +- src/components/sidebar/{ => types}/types.ts | 0 src/components/sidebar/{ => utils}/utils.ts | 4 +- src/components/{ => sidebar/view}/Sidebar.tsx | 22 ++-- .../subcomponents}/SidebarCollapsed.tsx | 0 .../subcomponents}/SidebarContent.tsx | 6 +- .../subcomponents}/SidebarFooter.tsx | 4 +- .../subcomponents}/SidebarHeader.tsx | 6 +- .../subcomponents}/SidebarModals.tsx | 14 +-- .../subcomponents}/SidebarProjectItem.tsx | 12 +- .../subcomponents}/SidebarProjectList.tsx | 4 +- .../subcomponents}/SidebarProjectSessions.tsx | 6 +- .../subcomponents}/SidebarProjectsState.tsx | 2 +- .../subcomponents}/SidebarSessionItem.tsx | 16 +-- src/hooks/useAudioRecorder.js | 109 ------------------ 34 files changed, 124 insertions(+), 233 deletions(-) rename src/{hooks/chat => components/chat/hooks}/useChatComposerState.ts (98%) rename src/{hooks/chat => components/chat/hooks}/useChatProviderState.ts (95%) rename src/{hooks/chat => components/chat/hooks}/useChatRealtimeHandlers.ts (99%) rename src/{hooks/chat => components/chat/hooks}/useChatSessionState.ts (98%) rename src/{hooks/chat => components/chat/hooks}/useFileMentions.tsx (97%) rename src/{hooks/chat => components/chat/hooks}/useSlashCommands.ts (98%) rename src/components/{ => chat/view}/ChatInterface.tsx (94%) rename src/{hooks/main-content => components/main-content/hooks}/useEditorSidebar.ts (95%) rename src/{hooks/main-content => components/main-content/hooks}/useMobileMenuHandlers.ts (100%) rename src/components/main-content/{ => types}/types.ts (97%) rename src/components/{ => main-content/view}/MainContent.tsx (85%) rename src/components/main-content/{ => view/subcomponents}/EditorSidebar.tsx (93%) rename src/components/main-content/{ => view/subcomponents}/MainContentHeader.tsx (94%) rename src/components/main-content/{ => view/subcomponents}/MainContentStateView.tsx (97%) rename src/components/main-content/{ => view/subcomponents}/MainContentTabSwitcher.tsx (96%) rename src/components/main-content/{ => view/subcomponents}/MainContentTitle.tsx (94%) rename src/components/main-content/{ => view/subcomponents}/MobileMenuButton.tsx (87%) rename src/components/main-content/{ => view/subcomponents}/TaskMasterPanel.tsx (94%) rename src/{ => components/sidebar}/hooks/useSidebarController.ts (98%) rename src/components/sidebar/{ => types}/types.ts (100%) rename src/components/sidebar/{ => utils}/utils.ts (98%) rename src/components/{ => sidebar/view}/Sidebar.tsx (89%) rename src/components/sidebar/{ => view/subcomponents}/SidebarCollapsed.tsx (100%) rename src/components/sidebar/{ => view/subcomponents}/SidebarContent.tsx (92%) rename src/components/sidebar/{ => view/subcomponents}/SidebarFooter.tsx (97%) rename src/components/sidebar/{ => view/subcomponents}/SidebarHeader.tsx (97%) rename src/components/sidebar/{ => view/subcomponents}/SidebarModals.tsx (94%) rename src/components/sidebar/{ => view/subcomponents}/SidebarProjectItem.tsx (98%) rename src/components/sidebar/{ => view/subcomponents}/SidebarProjectList.tsx (98%) rename src/components/sidebar/{ => view/subcomponents}/SidebarProjectSessions.tsx (98%) rename src/components/sidebar/{ => view/subcomponents}/SidebarProjectsState.tsx (97%) rename src/components/sidebar/{ => view/subcomponents}/SidebarSessionItem.tsx (96%) delete mode 100755 src/hooks/useAudioRecorder.js diff --git a/src/components/app/AppContent.tsx b/src/components/app/AppContent.tsx index 79743c4..df2f818 100644 --- a/src/components/app/AppContent.tsx +++ b/src/components/app/AppContent.tsx @@ -2,8 +2,8 @@ import { useEffect } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; -import Sidebar from '../Sidebar'; -import MainContent from '../MainContent'; +import Sidebar from '../sidebar/view/Sidebar'; +import MainContent from '../main-content/view/MainContent'; import MobileNav from '../MobileNav'; import { useWebSocket } from '../../contexts/WebSocketContext'; diff --git a/src/hooks/chat/useChatComposerState.ts b/src/components/chat/hooks/useChatComposerState.ts similarity index 98% rename from src/hooks/chat/useChatComposerState.ts rename to src/components/chat/hooks/useChatComposerState.ts index a04ab62..4cf8804 100644 --- a/src/hooks/chat/useChatComposerState.ts +++ b/src/components/chat/hooks/useChatComposerState.ts @@ -10,19 +10,19 @@ import type { TouchEvent, } from 'react'; import { useDropzone } from 'react-dropzone'; -import { authenticatedFetch } from '../../utils/api'; -import { thinkingModes } from '../../components/ThinkingModeSelector.jsx'; -import { grantClaudeToolPermission } from '../../components/chat/utils/chatPermissions'; -import { safeLocalStorage } from '../../components/chat/utils/chatStorage'; +import { authenticatedFetch } from '../../../utils/api'; +import { thinkingModes } from '../../ThinkingModeSelector.jsx'; +import { grantClaudeToolPermission } from '../utils/chatPermissions'; +import { safeLocalStorage } from '../utils/chatStorage'; import type { ChatMessage, PendingPermissionRequest, PermissionMode, Provider, -} from '../../components/chat/types'; +} from '../types'; import { useFileMentions } from './useFileMentions'; import { type SlashCommand, useSlashCommands } from './useSlashCommands'; -import type { Project, ProjectSession } from '../../types/app'; +import type { Project, ProjectSession } from '../../../types/app'; type PendingViewSession = { sessionId: string | null; diff --git a/src/hooks/chat/useChatProviderState.ts b/src/components/chat/hooks/useChatProviderState.ts similarity index 95% rename from src/hooks/chat/useChatProviderState.ts rename to src/components/chat/hooks/useChatProviderState.ts index 2a21d4e..e9c3f89 100644 --- a/src/hooks/chat/useChatProviderState.ts +++ b/src/components/chat/hooks/useChatProviderState.ts @@ -1,8 +1,8 @@ import { useCallback, useEffect, useRef, useState } from 'react'; -import { authenticatedFetch } from '../../utils/api'; -import { CLAUDE_MODELS, CODEX_MODELS, CURSOR_MODELS } from '../../../shared/modelConstants'; -import type { PendingPermissionRequest, PermissionMode, Provider } from '../../components/chat/types'; -import type { ProjectSession } from '../../types/app'; +import { authenticatedFetch } from '../../../utils/api'; +import { CLAUDE_MODELS, CODEX_MODELS, CURSOR_MODELS } from '../../../../shared/modelConstants'; +import type { PendingPermissionRequest, PermissionMode, Provider } from '../types'; +import type { ProjectSession } from '../../../types/app'; interface UseChatProviderStateArgs { selectedSession: ProjectSession | null; diff --git a/src/hooks/chat/useChatRealtimeHandlers.ts b/src/components/chat/hooks/useChatRealtimeHandlers.ts similarity index 99% rename from src/hooks/chat/useChatRealtimeHandlers.ts rename to src/components/chat/hooks/useChatRealtimeHandlers.ts index ae629d1..35659a3 100644 --- a/src/hooks/chat/useChatRealtimeHandlers.ts +++ b/src/components/chat/hooks/useChatRealtimeHandlers.ts @@ -1,9 +1,9 @@ import { useEffect } from 'react'; import type { Dispatch, MutableRefObject, SetStateAction } from 'react'; -import { decodeHtmlEntities, formatUsageLimitText } from '../../components/chat/utils/chatFormatting'; -import { safeLocalStorage } from '../../components/chat/utils/chatStorage'; -import type { ChatMessage, PendingPermissionRequest, Provider } from '../../components/chat/types'; -import type { Project, ProjectSession } from '../../types/app'; +import { decodeHtmlEntities, formatUsageLimitText } from '../utils/chatFormatting'; +import { safeLocalStorage } from '../utils/chatStorage'; +import type { ChatMessage, PendingPermissionRequest, Provider } from '../types'; +import type { Project, ProjectSession } from '../../../types/app'; type PendingViewSession = { sessionId: string | null; diff --git a/src/hooks/chat/useChatSessionState.ts b/src/components/chat/hooks/useChatSessionState.ts similarity index 98% rename from src/hooks/chat/useChatSessionState.ts rename to src/components/chat/hooks/useChatSessionState.ts index 7e42c03..efa8925 100644 --- a/src/hooks/chat/useChatSessionState.ts +++ b/src/components/chat/hooks/useChatSessionState.ts @@ -1,15 +1,15 @@ import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'; import type { MutableRefObject } from 'react'; -import { api, authenticatedFetch } from '../../utils/api'; -import type { ChatMessage, Provider } from '../../components/chat/types'; -import type { Project, ProjectSession } from '../../types/app'; -import { safeLocalStorage } from '../../components/chat/utils/chatStorage'; +import { api, authenticatedFetch } from '../../../utils/api'; +import type { ChatMessage, Provider } from '../types'; +import type { Project, ProjectSession } from '../../../types/app'; +import { safeLocalStorage } from '../utils/chatStorage'; import { convertCursorSessionMessages, convertSessionMessages, createCachedDiffCalculator, type DiffCalculator, -} from '../../components/chat/utils/messageTransforms'; +} from '../utils/messageTransforms'; const MESSAGES_PER_PAGE = 20; const INITIAL_VISIBLE_MESSAGES = 100; diff --git a/src/hooks/chat/useFileMentions.tsx b/src/components/chat/hooks/useFileMentions.tsx similarity index 97% rename from src/hooks/chat/useFileMentions.tsx rename to src/components/chat/hooks/useFileMentions.tsx index 0ff623a..1a6d2ab 100644 --- a/src/hooks/chat/useFileMentions.tsx +++ b/src/components/chat/hooks/useFileMentions.tsx @@ -1,8 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react'; -import { api } from '../../utils/api'; -import { escapeRegExp } from '../../components/chat/utils/chatFormatting'; -import type { Project } from '../../types/app'; +import { api } from '../../../utils/api'; +import { escapeRegExp } from '../utils/chatFormatting'; +import type { Project } from '../../../types/app'; interface ProjectFileNode { name: string; diff --git a/src/hooks/chat/useSlashCommands.ts b/src/components/chat/hooks/useSlashCommands.ts similarity index 98% rename from src/hooks/chat/useSlashCommands.ts rename to src/components/chat/hooks/useSlashCommands.ts index 8df29b2..f14fc43 100644 --- a/src/hooks/chat/useSlashCommands.ts +++ b/src/components/chat/hooks/useSlashCommands.ts @@ -1,9 +1,9 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react'; import Fuse from 'fuse.js'; -import { authenticatedFetch } from '../../utils/api'; -import { safeLocalStorage } from '../../components/chat/utils/chatStorage'; -import type { Project } from '../../types/app'; +import { authenticatedFetch } from '../../../utils/api'; +import { safeLocalStorage } from '../utils/chatStorage'; +import type { Project } from '../../../types/app'; const COMMAND_QUERY_DEBOUNCE_MS = 150; diff --git a/src/components/ChatInterface.tsx b/src/components/chat/view/ChatInterface.tsx similarity index 94% rename from src/components/ChatInterface.tsx rename to src/components/chat/view/ChatInterface.tsx index 70554e5..a820ef2 100644 --- a/src/components/ChatInterface.tsx +++ b/src/components/chat/view/ChatInterface.tsx @@ -1,15 +1,15 @@ import React, { useCallback, useEffect, useRef } from 'react'; -import QuickSettingsPanel from './QuickSettingsPanel'; -import { useTasksSettings } from '../contexts/TasksSettingsContext'; +import QuickSettingsPanel from '../../QuickSettingsPanel'; +import { useTasksSettings } from '../../../contexts/TasksSettingsContext'; import { useTranslation } from 'react-i18next'; -import ChatMessagesPane from './chat/view/ChatMessagesPane'; -import ChatComposer from './chat/view/ChatComposer'; -import type { ChatInterfaceProps } from './chat/types'; -import { useChatProviderState } from '../hooks/chat/useChatProviderState'; -import { useChatSessionState } from '../hooks/chat/useChatSessionState'; -import { useChatRealtimeHandlers } from '../hooks/chat/useChatRealtimeHandlers'; -import { useChatComposerState } from '../hooks/chat/useChatComposerState'; -import type { Provider } from './chat/types'; +import ChatMessagesPane from './ChatMessagesPane'; +import ChatComposer from './ChatComposer'; +import type { ChatInterfaceProps } from '../types'; +import { useChatProviderState } from '../hooks/useChatProviderState'; +import { useChatSessionState } from '../hooks/useChatSessionState'; +import { useChatRealtimeHandlers } from '../hooks/useChatRealtimeHandlers'; +import { useChatComposerState } from '../hooks/useChatComposerState'; +import type { Provider } from '../types'; type PendingViewSession = { sessionId: string | null; diff --git a/src/hooks/main-content/useEditorSidebar.ts b/src/components/main-content/hooks/useEditorSidebar.ts similarity index 95% rename from src/hooks/main-content/useEditorSidebar.ts rename to src/components/main-content/hooks/useEditorSidebar.ts index 9ca57fe..e55e334 100644 --- a/src/hooks/main-content/useEditorSidebar.ts +++ b/src/components/main-content/hooks/useEditorSidebar.ts @@ -1,7 +1,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'; import type { MouseEvent as ReactMouseEvent } from 'react'; -import type { Project } from '../../types/app'; -import type { DiffInfo, EditingFile } from '../../components/main-content/types'; +import type { Project } from '../../../types/app'; +import type { DiffInfo, EditingFile } from '../types/types'; type UseEditorSidebarOptions = { selectedProject: Project | null; diff --git a/src/hooks/main-content/useMobileMenuHandlers.ts b/src/components/main-content/hooks/useMobileMenuHandlers.ts similarity index 100% rename from src/hooks/main-content/useMobileMenuHandlers.ts rename to src/components/main-content/hooks/useMobileMenuHandlers.ts diff --git a/src/components/main-content/types.ts b/src/components/main-content/types/types.ts similarity index 97% rename from src/components/main-content/types.ts rename to src/components/main-content/types/types.ts index 2ebcfc3..c91e60e 100644 --- a/src/components/main-content/types.ts +++ b/src/components/main-content/types/types.ts @@ -1,5 +1,5 @@ import type { Dispatch, MouseEvent, RefObject, SetStateAction } from 'react'; -import type { AppTab, Project, ProjectSession } from '../../types/app'; +import type { AppTab, Project, ProjectSession } from '../../../types/app'; export type SessionLifecycleHandler = (sessionId?: string | null) => void; diff --git a/src/components/MainContent.tsx b/src/components/main-content/view/MainContent.tsx similarity index 85% rename from src/components/MainContent.tsx rename to src/components/main-content/view/MainContent.tsx index a42e017..1db3315 100644 --- a/src/components/MainContent.tsx +++ b/src/components/main-content/view/MainContent.tsx @@ -1,22 +1,22 @@ import React, { useEffect } from 'react'; -import ChatInterface from './ChatInterface'; -import FileTree from './FileTree'; -import StandaloneShell from './StandaloneShell'; -import GitPanel from './GitPanel'; -import ErrorBoundary from './ErrorBoundary'; +import ChatInterface from '../../chat/view/ChatInterface'; +import FileTree from '../../FileTree'; +import StandaloneShell from '../../StandaloneShell'; +import GitPanel from '../../GitPanel'; +import ErrorBoundary from '../../ErrorBoundary'; -import MainContentHeader from './main-content/MainContentHeader'; -import MainContentStateView from './main-content/MainContentStateView'; -import EditorSidebar from './main-content/EditorSidebar'; -import TaskMasterPanel from './main-content/TaskMasterPanel'; -import type { MainContentProps } from './main-content/types'; +import MainContentHeader from './subcomponents/MainContentHeader'; +import MainContentStateView from './subcomponents/MainContentStateView'; +import EditorSidebar from './subcomponents/EditorSidebar'; +import TaskMasterPanel from './subcomponents/TaskMasterPanel'; +import type { MainContentProps } from '../types/types'; -import { useTaskMaster } from '../contexts/TaskMasterContext'; -import { useTasksSettings } from '../contexts/TasksSettingsContext'; -import { useUiPreferences } from '../hooks/useUiPreferences'; -import { useEditorSidebar } from '../hooks/main-content/useEditorSidebar'; -import type { Project } from '../types/app'; +import { useTaskMaster } from '../../../contexts/TaskMasterContext'; +import { useTasksSettings } from '../../../contexts/TasksSettingsContext'; +import { useUiPreferences } from '../../../hooks/useUiPreferences'; +import { useEditorSidebar } from '../hooks/useEditorSidebar'; +import type { Project } from '../../../types/app'; const AnyStandaloneShell = StandaloneShell as any; const AnyGitPanel = GitPanel as any; diff --git a/src/components/main-content/EditorSidebar.tsx b/src/components/main-content/view/subcomponents/EditorSidebar.tsx similarity index 93% rename from src/components/main-content/EditorSidebar.tsx rename to src/components/main-content/view/subcomponents/EditorSidebar.tsx index 78fe2c4..591a3b8 100644 --- a/src/components/main-content/EditorSidebar.tsx +++ b/src/components/main-content/view/subcomponents/EditorSidebar.tsx @@ -1,5 +1,5 @@ -import CodeEditor from '../CodeEditor'; -import type { EditorSidebarProps } from './types'; +import CodeEditor from '../../../CodeEditor'; +import type { EditorSidebarProps } from '../../types/types'; const AnyCodeEditor = CodeEditor as any; diff --git a/src/components/main-content/MainContentHeader.tsx b/src/components/main-content/view/subcomponents/MainContentHeader.tsx similarity index 94% rename from src/components/main-content/MainContentHeader.tsx rename to src/components/main-content/view/subcomponents/MainContentHeader.tsx index 81e3739..d1cc74a 100644 --- a/src/components/main-content/MainContentHeader.tsx +++ b/src/components/main-content/view/subcomponents/MainContentHeader.tsx @@ -1,7 +1,7 @@ import MobileMenuButton from './MobileMenuButton'; import MainContentTabSwitcher from './MainContentTabSwitcher'; import MainContentTitle from './MainContentTitle'; -import type { MainContentHeaderProps } from './types'; +import type { MainContentHeaderProps } from '../../types/types'; export default function MainContentHeader({ activeTab, diff --git a/src/components/main-content/MainContentStateView.tsx b/src/components/main-content/view/subcomponents/MainContentStateView.tsx similarity index 97% rename from src/components/main-content/MainContentStateView.tsx rename to src/components/main-content/view/subcomponents/MainContentStateView.tsx index f9b4e14..ada5c52 100644 --- a/src/components/main-content/MainContentStateView.tsx +++ b/src/components/main-content/view/subcomponents/MainContentStateView.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import MobileMenuButton from './MobileMenuButton'; -import type { MainContentStateViewProps } from './types'; +import type { MainContentStateViewProps } from '../../types/types'; export default function MainContentStateView({ mode, isMobile, onMenuClick }: MainContentStateViewProps) { const { t } = useTranslation(); diff --git a/src/components/main-content/MainContentTabSwitcher.tsx b/src/components/main-content/view/subcomponents/MainContentTabSwitcher.tsx similarity index 96% rename from src/components/main-content/MainContentTabSwitcher.tsx rename to src/components/main-content/view/subcomponents/MainContentTabSwitcher.tsx index 5625165..f1938be 100644 --- a/src/components/main-content/MainContentTabSwitcher.tsx +++ b/src/components/main-content/view/subcomponents/MainContentTabSwitcher.tsx @@ -1,5 +1,5 @@ -import Tooltip from '../Tooltip'; -import type { AppTab } from '../../types/app'; +import Tooltip from '../../../Tooltip'; +import type { AppTab } from '../../../../types/app'; import type { Dispatch, SetStateAction } from 'react'; import { useTranslation } from 'react-i18next'; diff --git a/src/components/main-content/MainContentTitle.tsx b/src/components/main-content/view/subcomponents/MainContentTitle.tsx similarity index 94% rename from src/components/main-content/MainContentTitle.tsx rename to src/components/main-content/view/subcomponents/MainContentTitle.tsx index 285a881..174c467 100644 --- a/src/components/main-content/MainContentTitle.tsx +++ b/src/components/main-content/view/subcomponents/MainContentTitle.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; -import SessionProviderLogo from '../SessionProviderLogo'; -import type { AppTab, Project, ProjectSession } from '../../types/app'; +import SessionProviderLogo from '../../../SessionProviderLogo'; +import type { AppTab, Project, ProjectSession } from '../../../../types/app'; type MainContentTitleProps = { activeTab: AppTab; diff --git a/src/components/main-content/MobileMenuButton.tsx b/src/components/main-content/view/subcomponents/MobileMenuButton.tsx similarity index 87% rename from src/components/main-content/MobileMenuButton.tsx rename to src/components/main-content/view/subcomponents/MobileMenuButton.tsx index 405558e..2333e4b 100644 --- a/src/components/main-content/MobileMenuButton.tsx +++ b/src/components/main-content/view/subcomponents/MobileMenuButton.tsx @@ -1,5 +1,5 @@ -import type { MobileMenuButtonProps } from './types'; -import { useMobileMenuHandlers } from '../../hooks/main-content/useMobileMenuHandlers'; +import type { MobileMenuButtonProps } from '../../types/types'; +import { useMobileMenuHandlers } from '../../hooks/useMobileMenuHandlers'; export default function MobileMenuButton({ onMenuClick, compact = false }: MobileMenuButtonProps) { const { handleMobileMenuClick, handleMobileMenuTouchEnd } = useMobileMenuHandlers(onMenuClick); diff --git a/src/components/main-content/TaskMasterPanel.tsx b/src/components/main-content/view/subcomponents/TaskMasterPanel.tsx similarity index 94% rename from src/components/main-content/TaskMasterPanel.tsx rename to src/components/main-content/view/subcomponents/TaskMasterPanel.tsx index cc7df38..91810cf 100644 --- a/src/components/main-content/TaskMasterPanel.tsx +++ b/src/components/main-content/view/subcomponents/TaskMasterPanel.tsx @@ -1,11 +1,11 @@ import { useCallback, useEffect, useRef, useState } from 'react'; -import TaskList from '../TaskList'; -import TaskDetail from '../TaskDetail'; -import PRDEditor from '../PRDEditor'; -import { useTaskMaster } from '../../contexts/TaskMasterContext'; -import { api } from '../../utils/api'; -import type { Project } from '../../types/app'; -import type { PrdFile, TaskMasterPanelProps, TaskMasterTask, TaskSelection } from './types'; +import TaskList from '../../../TaskList'; +import TaskDetail from '../../../TaskDetail'; +import PRDEditor from '../../../PRDEditor'; +import { useTaskMaster } from '../../../../contexts/TaskMasterContext'; +import { api } from '../../../../utils/api'; +import type { Project } from '../../../../types/app'; +import type { PrdFile, TaskMasterPanelProps, TaskMasterTask, TaskSelection } from '../../types/types'; const AnyTaskList = TaskList as any; const AnyTaskDetail = TaskDetail as any; diff --git a/src/hooks/useSidebarController.ts b/src/components/sidebar/hooks/useSidebarController.ts similarity index 98% rename from src/hooks/useSidebarController.ts rename to src/components/sidebar/hooks/useSidebarController.ts index 4549767..a6d3b41 100644 --- a/src/hooks/useSidebarController.ts +++ b/src/components/sidebar/hooks/useSidebarController.ts @@ -1,8 +1,8 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import type React from 'react'; import type { TFunction } from 'i18next'; -import { api } from '../utils/api'; -import type { Project, ProjectSession } from '../types/app'; +import { api } from '../../../utils/api'; +import type { Project, ProjectSession } from '../../../types/app'; import type { AdditionalSessionsByProject, DeleteProjectConfirmation, @@ -10,7 +10,7 @@ import type { ProjectSortOrder, SessionDeleteConfirmation, SessionWithProvider, -} from '../components/sidebar/types'; +} from '../types/types'; import { filterProjects, getAllSessions, @@ -18,7 +18,7 @@ import { persistStarredProjects, readProjectSortOrder, sortProjects, -} from '../components/sidebar/utils'; +} from '../utils/utils'; type UseSidebarControllerArgs = { projects: Project[]; diff --git a/src/components/sidebar/types.ts b/src/components/sidebar/types/types.ts similarity index 100% rename from src/components/sidebar/types.ts rename to src/components/sidebar/types/types.ts diff --git a/src/components/sidebar/utils.ts b/src/components/sidebar/utils/utils.ts similarity index 98% rename from src/components/sidebar/utils.ts rename to src/components/sidebar/utils/utils.ts index 1c8621b..348d78f 100644 --- a/src/components/sidebar/utils.ts +++ b/src/components/sidebar/utils/utils.ts @@ -1,11 +1,11 @@ import type { TFunction } from 'i18next'; -import type { Project } from '../../types/app'; +import type { Project } from '../../../types/app'; import type { AdditionalSessionsByProject, ProjectSortOrder, SessionViewModel, SessionWithProvider, -} from './types'; +} from '../types/types'; export const readProjectSortOrder = (): ProjectSortOrder => { try { diff --git a/src/components/Sidebar.tsx b/src/components/sidebar/view/Sidebar.tsx similarity index 89% rename from src/components/Sidebar.tsx rename to src/components/sidebar/view/Sidebar.tsx index 593f3f6..d8633c9 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/sidebar/view/Sidebar.tsx @@ -1,17 +1,17 @@ import { useEffect } from 'react'; import { useTranslation } from 'react-i18next'; -import { useDeviceSettings } from '../hooks/useDeviceSettings'; -import { useVersionCheck } from '../hooks/useVersionCheck'; -import { useUiPreferences } from '../hooks/useUiPreferences'; +import { useDeviceSettings } from '../../../hooks/useDeviceSettings'; +import { useVersionCheck } from '../../../hooks/useVersionCheck'; +import { useUiPreferences } from '../../../hooks/useUiPreferences'; import { useSidebarController } from '../hooks/useSidebarController'; -import { useTaskMaster } from '../contexts/TaskMasterContext'; -import { useTasksSettings } from '../contexts/TasksSettingsContext'; -import SidebarCollapsed from './sidebar/SidebarCollapsed'; -import SidebarContent from './sidebar/SidebarContent'; -import SidebarModals from './sidebar/SidebarModals'; -import type { Project } from '../types/app'; -import type { SidebarProjectListProps } from './sidebar/SidebarProjectList'; -import type { MCPServerStatus, SidebarProps } from './sidebar/types'; +import { useTaskMaster } from '../../../contexts/TaskMasterContext'; +import { useTasksSettings } from '../../../contexts/TasksSettingsContext'; +import SidebarCollapsed from './subcomponents/SidebarCollapsed'; +import SidebarContent from './subcomponents/SidebarContent'; +import SidebarModals from './subcomponents/SidebarModals'; +import type { Project } from '../../../types/app'; +import type { SidebarProjectListProps } from './subcomponents/SidebarProjectList'; +import type { MCPServerStatus, SidebarProps } from '../types/types'; type TaskMasterSidebarContext = { setCurrentProject: (project: Project) => void; diff --git a/src/components/sidebar/SidebarCollapsed.tsx b/src/components/sidebar/view/subcomponents/SidebarCollapsed.tsx similarity index 100% rename from src/components/sidebar/SidebarCollapsed.tsx rename to src/components/sidebar/view/subcomponents/SidebarCollapsed.tsx diff --git a/src/components/sidebar/SidebarContent.tsx b/src/components/sidebar/view/subcomponents/SidebarContent.tsx similarity index 92% rename from src/components/sidebar/SidebarContent.tsx rename to src/components/sidebar/view/subcomponents/SidebarContent.tsx index 5ec7e62..37b9874 100644 --- a/src/components/sidebar/SidebarContent.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarContent.tsx @@ -1,7 +1,7 @@ -import { ScrollArea } from '../ui/scroll-area'; +import { ScrollArea } from '../../../ui/scroll-area'; import type { TFunction } from 'i18next'; -import type { Project } from '../../types/app'; -import type { ReleaseInfo } from '../../types/sharedTypes'; +import type { Project } from '../../../../types/app'; +import type { ReleaseInfo } from '../../../../types/sharedTypes'; import SidebarFooter from './SidebarFooter'; import SidebarHeader from './SidebarHeader'; import SidebarProjectList, { type SidebarProjectListProps } from './SidebarProjectList'; diff --git a/src/components/sidebar/SidebarFooter.tsx b/src/components/sidebar/view/subcomponents/SidebarFooter.tsx similarity index 97% rename from src/components/sidebar/SidebarFooter.tsx rename to src/components/sidebar/view/subcomponents/SidebarFooter.tsx index 48fb41e..de9dcbc 100644 --- a/src/components/sidebar/SidebarFooter.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarFooter.tsx @@ -1,7 +1,7 @@ import { Settings } from 'lucide-react'; import type { TFunction } from 'i18next'; -import type { ReleaseInfo } from '../../types/sharedTypes'; -import { Button } from '../ui/button'; +import type { ReleaseInfo } from '../../../../types/sharedTypes'; +import { Button } from '../../../ui/button'; type SidebarFooterProps = { updateAvailable: boolean; diff --git a/src/components/sidebar/SidebarHeader.tsx b/src/components/sidebar/view/subcomponents/SidebarHeader.tsx similarity index 97% rename from src/components/sidebar/SidebarHeader.tsx rename to src/components/sidebar/view/subcomponents/SidebarHeader.tsx index 2866fe9..4b0ea22 100644 --- a/src/components/sidebar/SidebarHeader.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarHeader.tsx @@ -1,8 +1,8 @@ import { FolderPlus, MessageSquare, RefreshCw, Search, X } from 'lucide-react'; import type { TFunction } from 'i18next'; -import { Button } from '../ui/button'; -import { Input } from '../ui/input'; -import { IS_PLATFORM } from '../../constants/config'; +import { Button } from '../../../ui/button'; +import { Input } from '../../../ui/input'; +import { IS_PLATFORM } from '../../../../constants/config'; type SidebarHeaderProps = { isPWA: boolean; diff --git a/src/components/sidebar/SidebarModals.tsx b/src/components/sidebar/view/subcomponents/SidebarModals.tsx similarity index 94% rename from src/components/sidebar/SidebarModals.tsx rename to src/components/sidebar/view/subcomponents/SidebarModals.tsx index 6d94650..b51060f 100644 --- a/src/components/sidebar/SidebarModals.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarModals.tsx @@ -1,13 +1,13 @@ import ReactDOM from 'react-dom'; import { AlertTriangle, Trash2 } from 'lucide-react'; import type { TFunction } from 'i18next'; -import { Button } from '../ui/button'; -import ProjectCreationWizard from '../ProjectCreationWizard'; -import Settings from '../Settings'; -import VersionUpgradeModal from '../modals/VersionUpgradeModal'; -import type { Project } from '../../types/app'; -import type { ReleaseInfo } from '../../types/sharedTypes'; -import type { DeleteProjectConfirmation, SessionDeleteConfirmation } from './types'; +import { Button } from '../../../ui/button'; +import ProjectCreationWizard from '../../../ProjectCreationWizard'; +import Settings from '../../../Settings'; +import VersionUpgradeModal from '../../../modals/VersionUpgradeModal'; +import type { Project } from '../../../../types/app'; +import type { ReleaseInfo } from '../../../../types/sharedTypes'; +import type { DeleteProjectConfirmation, SessionDeleteConfirmation } from '../../types/types'; type SidebarModalsProps = { projects: Project[]; diff --git a/src/components/sidebar/SidebarProjectItem.tsx b/src/components/sidebar/view/subcomponents/SidebarProjectItem.tsx similarity index 98% rename from src/components/sidebar/SidebarProjectItem.tsx rename to src/components/sidebar/view/subcomponents/SidebarProjectItem.tsx index bcbaf84..7a072e1 100644 --- a/src/components/sidebar/SidebarProjectItem.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarProjectItem.tsx @@ -1,11 +1,11 @@ -import { Button } from '../ui/button'; +import { Button } from '../../../ui/button'; import { Check, ChevronDown, ChevronRight, Edit3, Folder, FolderOpen, Star, Trash2, X } from 'lucide-react'; import type { TFunction } from 'i18next'; -import { cn } from '../../lib/utils'; -import TaskIndicator from '../TaskIndicator'; -import type { Project, ProjectSession, SessionProvider } from '../../types/app'; -import type { MCPServerStatus, SessionWithProvider, TouchHandlerFactory } from './types'; -import { getTaskIndicatorStatus } from './utils'; +import { cn } from '../../../../lib/utils'; +import TaskIndicator from '../../../TaskIndicator'; +import type { Project, ProjectSession, SessionProvider } from '../../../../types/app'; +import type { MCPServerStatus, SessionWithProvider, TouchHandlerFactory } from '../../types/types'; +import { getTaskIndicatorStatus } from '../../utils/utils'; import SidebarProjectSessions from './SidebarProjectSessions'; type SidebarProjectItemProps = { diff --git a/src/components/sidebar/SidebarProjectList.tsx b/src/components/sidebar/view/subcomponents/SidebarProjectList.tsx similarity index 98% rename from src/components/sidebar/SidebarProjectList.tsx rename to src/components/sidebar/view/subcomponents/SidebarProjectList.tsx index 0718bfe..5571063 100644 --- a/src/components/sidebar/SidebarProjectList.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarProjectList.tsx @@ -1,11 +1,11 @@ import type { TFunction } from 'i18next'; -import type { LoadingProgress, Project, ProjectSession, SessionProvider } from '../../types/app'; +import type { LoadingProgress, Project, ProjectSession, SessionProvider } from '../../../../types/app'; import type { LoadingSessionsByProject, MCPServerStatus, SessionWithProvider, TouchHandlerFactory, -} from './types'; +} from '../../types/types'; import SidebarProjectItem from './SidebarProjectItem'; import SidebarProjectsState from './SidebarProjectsState'; diff --git a/src/components/sidebar/SidebarProjectSessions.tsx b/src/components/sidebar/view/subcomponents/SidebarProjectSessions.tsx similarity index 98% rename from src/components/sidebar/SidebarProjectSessions.tsx rename to src/components/sidebar/view/subcomponents/SidebarProjectSessions.tsx index 3cc63ef..e4ff955 100644 --- a/src/components/sidebar/SidebarProjectSessions.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarProjectSessions.tsx @@ -1,8 +1,8 @@ import { ChevronDown, Plus } from 'lucide-react'; import type { TFunction } from 'i18next'; -import { Button } from '../ui/button'; -import type { Project, ProjectSession, SessionProvider } from '../../types/app'; -import type { SessionWithProvider, TouchHandlerFactory } from './types'; +import { Button } from '../../../ui/button'; +import type { Project, ProjectSession, SessionProvider } from '../../../../types/app'; +import type { SessionWithProvider, TouchHandlerFactory } from '../../types/types'; import SidebarSessionItem from './SidebarSessionItem'; type SidebarProjectSessionsProps = { diff --git a/src/components/sidebar/SidebarProjectsState.tsx b/src/components/sidebar/view/subcomponents/SidebarProjectsState.tsx similarity index 97% rename from src/components/sidebar/SidebarProjectsState.tsx rename to src/components/sidebar/view/subcomponents/SidebarProjectsState.tsx index a9fa83a..8271a3f 100644 --- a/src/components/sidebar/SidebarProjectsState.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarProjectsState.tsx @@ -1,6 +1,6 @@ import { Folder, Search } from 'lucide-react'; import type { TFunction } from 'i18next'; -import type { LoadingProgress } from '../../types/app'; +import type { LoadingProgress } from '../../../../types/app'; type SidebarProjectsStateProps = { isLoading: boolean; diff --git a/src/components/sidebar/SidebarSessionItem.tsx b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx similarity index 96% rename from src/components/sidebar/SidebarSessionItem.tsx rename to src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx index 2105fad..fe856e6 100644 --- a/src/components/sidebar/SidebarSessionItem.tsx +++ b/src/components/sidebar/view/subcomponents/SidebarSessionItem.tsx @@ -1,13 +1,13 @@ -import { Badge } from '../ui/badge'; -import { Button } from '../ui/button'; +import { Badge } from '../../../ui/badge'; +import { Button } from '../../../ui/button'; import { Check, Clock, Edit2, Trash2, X } from 'lucide-react'; import type { TFunction } from 'i18next'; -import { cn } from '../../lib/utils'; -import { formatTimeAgo } from '../../utils/dateUtils'; -import type { Project, ProjectSession, SessionProvider } from '../../types/app'; -import type { SessionWithProvider, TouchHandlerFactory } from './types'; -import { createSessionViewModel } from './utils'; -import SessionProviderLogo from '../SessionProviderLogo'; +import { cn } from '../../../../lib/utils'; +import { formatTimeAgo } from '../../../../utils/dateUtils'; +import type { Project, ProjectSession, SessionProvider } from '../../../../types/app'; +import type { SessionWithProvider, TouchHandlerFactory } from '../../types/types'; +import { createSessionViewModel } from '../../utils/utils'; +import SessionProviderLogo from '../../../SessionProviderLogo'; type SidebarSessionItemProps = { project: Project; diff --git a/src/hooks/useAudioRecorder.js b/src/hooks/useAudioRecorder.js deleted file mode 100755 index c02fa34..0000000 --- a/src/hooks/useAudioRecorder.js +++ /dev/null @@ -1,109 +0,0 @@ -import { useState, useRef, useCallback } from 'react'; - -export function useAudioRecorder() { - const [isRecording, setRecording] = useState(false); - const [audioBlob, setAudioBlob] = useState(null); - const [error, setError] = useState(null); - const mediaRecorderRef = useRef(null); - const streamRef = useRef(null); - const chunksRef = useRef([]); - - const start = useCallback(async () => { - try { - setError(null); - setAudioBlob(null); - chunksRef.current = []; - - // Request microphone access - const stream = await navigator.mediaDevices.getUserMedia({ - audio: { - echoCancellation: true, - noiseSuppression: true, - sampleRate: 16000, - } - }); - - streamRef.current = stream; - - // Determine supported MIME type - const mimeType = MediaRecorder.isTypeSupported('audio/webm') - ? 'audio/webm' - : 'audio/mp4'; - - // Create media recorder - const recorder = new MediaRecorder(stream, { mimeType }); - mediaRecorderRef.current = recorder; - - // Set up event handlers - recorder.ondataavailable = (e) => { - if (e.data.size > 0) { - chunksRef.current.push(e.data); - } - }; - - recorder.onstop = () => { - // Create blob from chunks - const blob = new Blob(chunksRef.current, { type: mimeType }); - setAudioBlob(blob); - - // Clean up stream - if (streamRef.current) { - streamRef.current.getTracks().forEach(track => track.stop()); - streamRef.current = null; - } - }; - - recorder.onerror = (event) => { - console.error('MediaRecorder error:', event); - setError('Recording failed'); - setRecording(false); - }; - - // Start recording - recorder.start(); - setRecording(true); - console.log('Recording started'); - } catch (err) { - console.error('Failed to start recording:', err); - setError(err.message || 'Failed to start recording'); - setRecording(false); - } - }, []); - - const stop = useCallback(() => { - console.log('Stop called, recorder state:', mediaRecorderRef.current?.state); - - try { - if (mediaRecorderRef.current && mediaRecorderRef.current.state === 'recording') { - mediaRecorderRef.current.stop(); - console.log('Recording stopped'); - } - } catch (err) { - console.error('Error stopping recorder:', err); - } - - // Always update state - setRecording(false); - - // Clean up stream if still active - if (streamRef.current) { - streamRef.current.getTracks().forEach(track => track.stop()); - streamRef.current = null; - } - }, []); - - const reset = useCallback(() => { - setAudioBlob(null); - setError(null); - chunksRef.current = []; - }, []); - - return { - isRecording, - audioBlob, - error, - start, - stop, - reset - }; -} \ No newline at end of file