mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-02-14 12:47:33 +00:00
refactor: Restructure files and folders to better mimic feature-based architecture
This commit is contained in:
@@ -2,8 +2,8 @@ import { useEffect } from 'react';
|
|||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import Sidebar from '../Sidebar';
|
import Sidebar from '../sidebar/view/Sidebar';
|
||||||
import MainContent from '../MainContent';
|
import MainContent from '../main-content/view/MainContent';
|
||||||
import MobileNav from '../MobileNav';
|
import MobileNav from '../MobileNav';
|
||||||
|
|
||||||
import { useWebSocket } from '../../contexts/WebSocketContext';
|
import { useWebSocket } from '../../contexts/WebSocketContext';
|
||||||
|
|||||||
@@ -10,19 +10,19 @@ import type {
|
|||||||
TouchEvent,
|
TouchEvent,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { useDropzone } from 'react-dropzone';
|
import { useDropzone } from 'react-dropzone';
|
||||||
import { authenticatedFetch } from '../../utils/api';
|
import { authenticatedFetch } from '../../../utils/api';
|
||||||
import { thinkingModes } from '../../components/ThinkingModeSelector.jsx';
|
import { thinkingModes } from '../../ThinkingModeSelector.jsx';
|
||||||
import { grantClaudeToolPermission } from '../../components/chat/utils/chatPermissions';
|
import { grantClaudeToolPermission } from '../utils/chatPermissions';
|
||||||
import { safeLocalStorage } from '../../components/chat/utils/chatStorage';
|
import { safeLocalStorage } from '../utils/chatStorage';
|
||||||
import type {
|
import type {
|
||||||
ChatMessage,
|
ChatMessage,
|
||||||
PendingPermissionRequest,
|
PendingPermissionRequest,
|
||||||
PermissionMode,
|
PermissionMode,
|
||||||
Provider,
|
Provider,
|
||||||
} from '../../components/chat/types';
|
} from '../types';
|
||||||
import { useFileMentions } from './useFileMentions';
|
import { useFileMentions } from './useFileMentions';
|
||||||
import { type SlashCommand, useSlashCommands } from './useSlashCommands';
|
import { type SlashCommand, useSlashCommands } from './useSlashCommands';
|
||||||
import type { Project, ProjectSession } from '../../types/app';
|
import type { Project, ProjectSession } from '../../../types/app';
|
||||||
|
|
||||||
type PendingViewSession = {
|
type PendingViewSession = {
|
||||||
sessionId: string | null;
|
sessionId: string | null;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { authenticatedFetch } from '../../utils/api';
|
import { authenticatedFetch } from '../../../utils/api';
|
||||||
import { CLAUDE_MODELS, CODEX_MODELS, CURSOR_MODELS } from '../../../shared/modelConstants';
|
import { CLAUDE_MODELS, CODEX_MODELS, CURSOR_MODELS } from '../../../../shared/modelConstants';
|
||||||
import type { PendingPermissionRequest, PermissionMode, Provider } from '../../components/chat/types';
|
import type { PendingPermissionRequest, PermissionMode, Provider } from '../types';
|
||||||
import type { ProjectSession } from '../../types/app';
|
import type { ProjectSession } from '../../../types/app';
|
||||||
|
|
||||||
interface UseChatProviderStateArgs {
|
interface UseChatProviderStateArgs {
|
||||||
selectedSession: ProjectSession | null;
|
selectedSession: ProjectSession | null;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import type { Dispatch, MutableRefObject, SetStateAction } from 'react';
|
import type { Dispatch, MutableRefObject, SetStateAction } from 'react';
|
||||||
import { decodeHtmlEntities, formatUsageLimitText } from '../../components/chat/utils/chatFormatting';
|
import { decodeHtmlEntities, formatUsageLimitText } from '../utils/chatFormatting';
|
||||||
import { safeLocalStorage } from '../../components/chat/utils/chatStorage';
|
import { safeLocalStorage } from '../utils/chatStorage';
|
||||||
import type { ChatMessage, PendingPermissionRequest, Provider } from '../../components/chat/types';
|
import type { ChatMessage, PendingPermissionRequest, Provider } from '../types';
|
||||||
import type { Project, ProjectSession } from '../../types/app';
|
import type { Project, ProjectSession } from '../../../types/app';
|
||||||
|
|
||||||
type PendingViewSession = {
|
type PendingViewSession = {
|
||||||
sessionId: string | null;
|
sessionId: string | null;
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||||
import type { MutableRefObject } from 'react';
|
import type { MutableRefObject } from 'react';
|
||||||
import { api, authenticatedFetch } from '../../utils/api';
|
import { api, authenticatedFetch } from '../../../utils/api';
|
||||||
import type { ChatMessage, Provider } from '../../components/chat/types';
|
import type { ChatMessage, Provider } from '../types';
|
||||||
import type { Project, ProjectSession } from '../../types/app';
|
import type { Project, ProjectSession } from '../../../types/app';
|
||||||
import { safeLocalStorage } from '../../components/chat/utils/chatStorage';
|
import { safeLocalStorage } from '../utils/chatStorage';
|
||||||
import {
|
import {
|
||||||
convertCursorSessionMessages,
|
convertCursorSessionMessages,
|
||||||
convertSessionMessages,
|
convertSessionMessages,
|
||||||
createCachedDiffCalculator,
|
createCachedDiffCalculator,
|
||||||
type DiffCalculator,
|
type DiffCalculator,
|
||||||
} from '../../components/chat/utils/messageTransforms';
|
} from '../utils/messageTransforms';
|
||||||
|
|
||||||
const MESSAGES_PER_PAGE = 20;
|
const MESSAGES_PER_PAGE = 20;
|
||||||
const INITIAL_VISIBLE_MESSAGES = 100;
|
const INITIAL_VISIBLE_MESSAGES = 100;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react';
|
import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react';
|
||||||
import { api } from '../../utils/api';
|
import { api } from '../../../utils/api';
|
||||||
import { escapeRegExp } from '../../components/chat/utils/chatFormatting';
|
import { escapeRegExp } from '../utils/chatFormatting';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
|
|
||||||
interface ProjectFileNode {
|
interface ProjectFileNode {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react';
|
import type { Dispatch, KeyboardEvent, RefObject, SetStateAction } from 'react';
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js';
|
||||||
import { authenticatedFetch } from '../../utils/api';
|
import { authenticatedFetch } from '../../../utils/api';
|
||||||
import { safeLocalStorage } from '../../components/chat/utils/chatStorage';
|
import { safeLocalStorage } from '../utils/chatStorage';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
|
|
||||||
const COMMAND_QUERY_DEBOUNCE_MS = 150;
|
const COMMAND_QUERY_DEBOUNCE_MS = 150;
|
||||||
|
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import React, { useCallback, useEffect, useRef } from 'react';
|
import React, { useCallback, useEffect, useRef } from 'react';
|
||||||
import QuickSettingsPanel from './QuickSettingsPanel';
|
import QuickSettingsPanel from '../../QuickSettingsPanel';
|
||||||
import { useTasksSettings } from '../contexts/TasksSettingsContext';
|
import { useTasksSettings } from '../../../contexts/TasksSettingsContext';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import ChatMessagesPane from './chat/view/ChatMessagesPane';
|
import ChatMessagesPane from './ChatMessagesPane';
|
||||||
import ChatComposer from './chat/view/ChatComposer';
|
import ChatComposer from './ChatComposer';
|
||||||
import type { ChatInterfaceProps } from './chat/types';
|
import type { ChatInterfaceProps } from '../types';
|
||||||
import { useChatProviderState } from '../hooks/chat/useChatProviderState';
|
import { useChatProviderState } from '../hooks/useChatProviderState';
|
||||||
import { useChatSessionState } from '../hooks/chat/useChatSessionState';
|
import { useChatSessionState } from '../hooks/useChatSessionState';
|
||||||
import { useChatRealtimeHandlers } from '../hooks/chat/useChatRealtimeHandlers';
|
import { useChatRealtimeHandlers } from '../hooks/useChatRealtimeHandlers';
|
||||||
import { useChatComposerState } from '../hooks/chat/useChatComposerState';
|
import { useChatComposerState } from '../hooks/useChatComposerState';
|
||||||
import type { Provider } from './chat/types';
|
import type { Provider } from '../types';
|
||||||
|
|
||||||
type PendingViewSession = {
|
type PendingViewSession = {
|
||||||
sessionId: string | null;
|
sessionId: string | null;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import type { MouseEvent as ReactMouseEvent } from 'react';
|
import type { MouseEvent as ReactMouseEvent } from 'react';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
import type { DiffInfo, EditingFile } from '../../components/main-content/types';
|
import type { DiffInfo, EditingFile } from '../types/types';
|
||||||
|
|
||||||
type UseEditorSidebarOptions = {
|
type UseEditorSidebarOptions = {
|
||||||
selectedProject: Project | null;
|
selectedProject: Project | null;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { Dispatch, MouseEvent, RefObject, SetStateAction } from 'react';
|
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;
|
export type SessionLifecycleHandler = (sessionId?: string | null) => void;
|
||||||
|
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import React, { useEffect } from 'react';
|
import React, { useEffect } from 'react';
|
||||||
|
|
||||||
import ChatInterface from './ChatInterface';
|
import ChatInterface from '../../chat/view/ChatInterface';
|
||||||
import FileTree from './FileTree';
|
import FileTree from '../../FileTree';
|
||||||
import StandaloneShell from './StandaloneShell';
|
import StandaloneShell from '../../StandaloneShell';
|
||||||
import GitPanel from './GitPanel';
|
import GitPanel from '../../GitPanel';
|
||||||
import ErrorBoundary from './ErrorBoundary';
|
import ErrorBoundary from '../../ErrorBoundary';
|
||||||
|
|
||||||
import MainContentHeader from './main-content/MainContentHeader';
|
import MainContentHeader from './subcomponents/MainContentHeader';
|
||||||
import MainContentStateView from './main-content/MainContentStateView';
|
import MainContentStateView from './subcomponents/MainContentStateView';
|
||||||
import EditorSidebar from './main-content/EditorSidebar';
|
import EditorSidebar from './subcomponents/EditorSidebar';
|
||||||
import TaskMasterPanel from './main-content/TaskMasterPanel';
|
import TaskMasterPanel from './subcomponents/TaskMasterPanel';
|
||||||
import type { MainContentProps } from './main-content/types';
|
import type { MainContentProps } from '../types/types';
|
||||||
|
|
||||||
import { useTaskMaster } from '../contexts/TaskMasterContext';
|
import { useTaskMaster } from '../../../contexts/TaskMasterContext';
|
||||||
import { useTasksSettings } from '../contexts/TasksSettingsContext';
|
import { useTasksSettings } from '../../../contexts/TasksSettingsContext';
|
||||||
import { useUiPreferences } from '../hooks/useUiPreferences';
|
import { useUiPreferences } from '../../../hooks/useUiPreferences';
|
||||||
import { useEditorSidebar } from '../hooks/main-content/useEditorSidebar';
|
import { useEditorSidebar } from '../hooks/useEditorSidebar';
|
||||||
import type { Project } from '../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
|
|
||||||
const AnyStandaloneShell = StandaloneShell as any;
|
const AnyStandaloneShell = StandaloneShell as any;
|
||||||
const AnyGitPanel = GitPanel as any;
|
const AnyGitPanel = GitPanel as any;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import CodeEditor from '../CodeEditor';
|
import CodeEditor from '../../../CodeEditor';
|
||||||
import type { EditorSidebarProps } from './types';
|
import type { EditorSidebarProps } from '../../types/types';
|
||||||
|
|
||||||
const AnyCodeEditor = CodeEditor as any;
|
const AnyCodeEditor = CodeEditor as any;
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import MobileMenuButton from './MobileMenuButton';
|
import MobileMenuButton from './MobileMenuButton';
|
||||||
import MainContentTabSwitcher from './MainContentTabSwitcher';
|
import MainContentTabSwitcher from './MainContentTabSwitcher';
|
||||||
import MainContentTitle from './MainContentTitle';
|
import MainContentTitle from './MainContentTitle';
|
||||||
import type { MainContentHeaderProps } from './types';
|
import type { MainContentHeaderProps } from '../../types/types';
|
||||||
|
|
||||||
export default function MainContentHeader({
|
export default function MainContentHeader({
|
||||||
activeTab,
|
activeTab,
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import MobileMenuButton from './MobileMenuButton';
|
import MobileMenuButton from './MobileMenuButton';
|
||||||
import type { MainContentStateViewProps } from './types';
|
import type { MainContentStateViewProps } from '../../types/types';
|
||||||
|
|
||||||
export default function MainContentStateView({ mode, isMobile, onMenuClick }: MainContentStateViewProps) {
|
export default function MainContentStateView({ mode, isMobile, onMenuClick }: MainContentStateViewProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import Tooltip from '../Tooltip';
|
import Tooltip from '../../../Tooltip';
|
||||||
import type { AppTab } from '../../types/app';
|
import type { AppTab } from '../../../../types/app';
|
||||||
import type { Dispatch, SetStateAction } from 'react';
|
import type { Dispatch, SetStateAction } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import SessionProviderLogo from '../SessionProviderLogo';
|
import SessionProviderLogo from '../../../SessionProviderLogo';
|
||||||
import type { AppTab, Project, ProjectSession } from '../../types/app';
|
import type { AppTab, Project, ProjectSession } from '../../../../types/app';
|
||||||
|
|
||||||
type MainContentTitleProps = {
|
type MainContentTitleProps = {
|
||||||
activeTab: AppTab;
|
activeTab: AppTab;
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import type { MobileMenuButtonProps } from './types';
|
import type { MobileMenuButtonProps } from '../../types/types';
|
||||||
import { useMobileMenuHandlers } from '../../hooks/main-content/useMobileMenuHandlers';
|
import { useMobileMenuHandlers } from '../../hooks/useMobileMenuHandlers';
|
||||||
|
|
||||||
export default function MobileMenuButton({ onMenuClick, compact = false }: MobileMenuButtonProps) {
|
export default function MobileMenuButton({ onMenuClick, compact = false }: MobileMenuButtonProps) {
|
||||||
const { handleMobileMenuClick, handleMobileMenuTouchEnd } = useMobileMenuHandlers(onMenuClick);
|
const { handleMobileMenuClick, handleMobileMenuTouchEnd } = useMobileMenuHandlers(onMenuClick);
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import TaskList from '../TaskList';
|
import TaskList from '../../../TaskList';
|
||||||
import TaskDetail from '../TaskDetail';
|
import TaskDetail from '../../../TaskDetail';
|
||||||
import PRDEditor from '../PRDEditor';
|
import PRDEditor from '../../../PRDEditor';
|
||||||
import { useTaskMaster } from '../../contexts/TaskMasterContext';
|
import { useTaskMaster } from '../../../../contexts/TaskMasterContext';
|
||||||
import { api } from '../../utils/api';
|
import { api } from '../../../../utils/api';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../../types/app';
|
||||||
import type { PrdFile, TaskMasterPanelProps, TaskMasterTask, TaskSelection } from './types';
|
import type { PrdFile, TaskMasterPanelProps, TaskMasterTask, TaskSelection } from '../../types/types';
|
||||||
|
|
||||||
const AnyTaskList = TaskList as any;
|
const AnyTaskList = TaskList as any;
|
||||||
const AnyTaskDetail = TaskDetail as any;
|
const AnyTaskDetail = TaskDetail as any;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { api } from '../utils/api';
|
import { api } from '../../../utils/api';
|
||||||
import type { Project, ProjectSession } from '../types/app';
|
import type { Project, ProjectSession } from '../../../types/app';
|
||||||
import type {
|
import type {
|
||||||
AdditionalSessionsByProject,
|
AdditionalSessionsByProject,
|
||||||
DeleteProjectConfirmation,
|
DeleteProjectConfirmation,
|
||||||
@@ -10,7 +10,7 @@ import type {
|
|||||||
ProjectSortOrder,
|
ProjectSortOrder,
|
||||||
SessionDeleteConfirmation,
|
SessionDeleteConfirmation,
|
||||||
SessionWithProvider,
|
SessionWithProvider,
|
||||||
} from '../components/sidebar/types';
|
} from '../types/types';
|
||||||
import {
|
import {
|
||||||
filterProjects,
|
filterProjects,
|
||||||
getAllSessions,
|
getAllSessions,
|
||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
persistStarredProjects,
|
persistStarredProjects,
|
||||||
readProjectSortOrder,
|
readProjectSortOrder,
|
||||||
sortProjects,
|
sortProjects,
|
||||||
} from '../components/sidebar/utils';
|
} from '../utils/utils';
|
||||||
|
|
||||||
type UseSidebarControllerArgs = {
|
type UseSidebarControllerArgs = {
|
||||||
projects: Project[];
|
projects: Project[];
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
import type {
|
import type {
|
||||||
AdditionalSessionsByProject,
|
AdditionalSessionsByProject,
|
||||||
ProjectSortOrder,
|
ProjectSortOrder,
|
||||||
SessionViewModel,
|
SessionViewModel,
|
||||||
SessionWithProvider,
|
SessionWithProvider,
|
||||||
} from './types';
|
} from '../types/types';
|
||||||
|
|
||||||
export const readProjectSortOrder = (): ProjectSortOrder => {
|
export const readProjectSortOrder = (): ProjectSortOrder => {
|
||||||
try {
|
try {
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useDeviceSettings } from '../hooks/useDeviceSettings';
|
import { useDeviceSettings } from '../../../hooks/useDeviceSettings';
|
||||||
import { useVersionCheck } from '../hooks/useVersionCheck';
|
import { useVersionCheck } from '../../../hooks/useVersionCheck';
|
||||||
import { useUiPreferences } from '../hooks/useUiPreferences';
|
import { useUiPreferences } from '../../../hooks/useUiPreferences';
|
||||||
import { useSidebarController } from '../hooks/useSidebarController';
|
import { useSidebarController } from '../hooks/useSidebarController';
|
||||||
import { useTaskMaster } from '../contexts/TaskMasterContext';
|
import { useTaskMaster } from '../../../contexts/TaskMasterContext';
|
||||||
import { useTasksSettings } from '../contexts/TasksSettingsContext';
|
import { useTasksSettings } from '../../../contexts/TasksSettingsContext';
|
||||||
import SidebarCollapsed from './sidebar/SidebarCollapsed';
|
import SidebarCollapsed from './subcomponents/SidebarCollapsed';
|
||||||
import SidebarContent from './sidebar/SidebarContent';
|
import SidebarContent from './subcomponents/SidebarContent';
|
||||||
import SidebarModals from './sidebar/SidebarModals';
|
import SidebarModals from './subcomponents/SidebarModals';
|
||||||
import type { Project } from '../types/app';
|
import type { Project } from '../../../types/app';
|
||||||
import type { SidebarProjectListProps } from './sidebar/SidebarProjectList';
|
import type { SidebarProjectListProps } from './subcomponents/SidebarProjectList';
|
||||||
import type { MCPServerStatus, SidebarProps } from './sidebar/types';
|
import type { MCPServerStatus, SidebarProps } from '../types/types';
|
||||||
|
|
||||||
type TaskMasterSidebarContext = {
|
type TaskMasterSidebarContext = {
|
||||||
setCurrentProject: (project: Project) => void;
|
setCurrentProject: (project: Project) => void;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { ScrollArea } from '../ui/scroll-area';
|
import { ScrollArea } from '../../../ui/scroll-area';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../../types/app';
|
||||||
import type { ReleaseInfo } from '../../types/sharedTypes';
|
import type { ReleaseInfo } from '../../../../types/sharedTypes';
|
||||||
import SidebarFooter from './SidebarFooter';
|
import SidebarFooter from './SidebarFooter';
|
||||||
import SidebarHeader from './SidebarHeader';
|
import SidebarHeader from './SidebarHeader';
|
||||||
import SidebarProjectList, { type SidebarProjectListProps } from './SidebarProjectList';
|
import SidebarProjectList, { type SidebarProjectListProps } from './SidebarProjectList';
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Settings } from 'lucide-react';
|
import { Settings } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { ReleaseInfo } from '../../types/sharedTypes';
|
import type { ReleaseInfo } from '../../../../types/sharedTypes';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
|
|
||||||
type SidebarFooterProps = {
|
type SidebarFooterProps = {
|
||||||
updateAvailable: boolean;
|
updateAvailable: boolean;
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { FolderPlus, MessageSquare, RefreshCw, Search, X } from 'lucide-react';
|
import { FolderPlus, MessageSquare, RefreshCw, Search, X } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import { Input } from '../ui/input';
|
import { Input } from '../../../ui/input';
|
||||||
import { IS_PLATFORM } from '../../constants/config';
|
import { IS_PLATFORM } from '../../../../constants/config';
|
||||||
|
|
||||||
type SidebarHeaderProps = {
|
type SidebarHeaderProps = {
|
||||||
isPWA: boolean;
|
isPWA: boolean;
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import { AlertTriangle, Trash2 } from 'lucide-react';
|
import { AlertTriangle, Trash2 } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import ProjectCreationWizard from '../ProjectCreationWizard';
|
import ProjectCreationWizard from '../../../ProjectCreationWizard';
|
||||||
import Settings from '../Settings';
|
import Settings from '../../../Settings';
|
||||||
import VersionUpgradeModal from '../modals/VersionUpgradeModal';
|
import VersionUpgradeModal from '../../../modals/VersionUpgradeModal';
|
||||||
import type { Project } from '../../types/app';
|
import type { Project } from '../../../../types/app';
|
||||||
import type { ReleaseInfo } from '../../types/sharedTypes';
|
import type { ReleaseInfo } from '../../../../types/sharedTypes';
|
||||||
import type { DeleteProjectConfirmation, SessionDeleteConfirmation } from './types';
|
import type { DeleteProjectConfirmation, SessionDeleteConfirmation } from '../../types/types';
|
||||||
|
|
||||||
type SidebarModalsProps = {
|
type SidebarModalsProps = {
|
||||||
projects: Project[];
|
projects: Project[];
|
||||||
@@ -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 { Check, ChevronDown, ChevronRight, Edit3, Folder, FolderOpen, Star, Trash2, X } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { cn } from '../../lib/utils';
|
import { cn } from '../../../../lib/utils';
|
||||||
import TaskIndicator from '../TaskIndicator';
|
import TaskIndicator from '../../../TaskIndicator';
|
||||||
import type { Project, ProjectSession, SessionProvider } from '../../types/app';
|
import type { Project, ProjectSession, SessionProvider } from '../../../../types/app';
|
||||||
import type { MCPServerStatus, SessionWithProvider, TouchHandlerFactory } from './types';
|
import type { MCPServerStatus, SessionWithProvider, TouchHandlerFactory } from '../../types/types';
|
||||||
import { getTaskIndicatorStatus } from './utils';
|
import { getTaskIndicatorStatus } from '../../utils/utils';
|
||||||
import SidebarProjectSessions from './SidebarProjectSessions';
|
import SidebarProjectSessions from './SidebarProjectSessions';
|
||||||
|
|
||||||
type SidebarProjectItemProps = {
|
type SidebarProjectItemProps = {
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import type { TFunction } from 'i18next';
|
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 {
|
import type {
|
||||||
LoadingSessionsByProject,
|
LoadingSessionsByProject,
|
||||||
MCPServerStatus,
|
MCPServerStatus,
|
||||||
SessionWithProvider,
|
SessionWithProvider,
|
||||||
TouchHandlerFactory,
|
TouchHandlerFactory,
|
||||||
} from './types';
|
} from '../../types/types';
|
||||||
import SidebarProjectItem from './SidebarProjectItem';
|
import SidebarProjectItem from './SidebarProjectItem';
|
||||||
import SidebarProjectsState from './SidebarProjectsState';
|
import SidebarProjectsState from './SidebarProjectsState';
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import { ChevronDown, Plus } from 'lucide-react';
|
import { ChevronDown, Plus } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import type { Project, ProjectSession, SessionProvider } from '../../types/app';
|
import type { Project, ProjectSession, SessionProvider } from '../../../../types/app';
|
||||||
import type { SessionWithProvider, TouchHandlerFactory } from './types';
|
import type { SessionWithProvider, TouchHandlerFactory } from '../../types/types';
|
||||||
import SidebarSessionItem from './SidebarSessionItem';
|
import SidebarSessionItem from './SidebarSessionItem';
|
||||||
|
|
||||||
type SidebarProjectSessionsProps = {
|
type SidebarProjectSessionsProps = {
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Folder, Search } from 'lucide-react';
|
import { Folder, Search } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import type { LoadingProgress } from '../../types/app';
|
import type { LoadingProgress } from '../../../../types/app';
|
||||||
|
|
||||||
type SidebarProjectsStateProps = {
|
type SidebarProjectsStateProps = {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import { Badge } from '../ui/badge';
|
import { Badge } from '../../../ui/badge';
|
||||||
import { Button } from '../ui/button';
|
import { Button } from '../../../ui/button';
|
||||||
import { Check, Clock, Edit2, Trash2, X } from 'lucide-react';
|
import { Check, Clock, Edit2, Trash2, X } from 'lucide-react';
|
||||||
import type { TFunction } from 'i18next';
|
import type { TFunction } from 'i18next';
|
||||||
import { cn } from '../../lib/utils';
|
import { cn } from '../../../../lib/utils';
|
||||||
import { formatTimeAgo } from '../../utils/dateUtils';
|
import { formatTimeAgo } from '../../../../utils/dateUtils';
|
||||||
import type { Project, ProjectSession, SessionProvider } from '../../types/app';
|
import type { Project, ProjectSession, SessionProvider } from '../../../../types/app';
|
||||||
import type { SessionWithProvider, TouchHandlerFactory } from './types';
|
import type { SessionWithProvider, TouchHandlerFactory } from '../../types/types';
|
||||||
import { createSessionViewModel } from './utils';
|
import { createSessionViewModel } from '../../utils/utils';
|
||||||
import SessionProviderLogo from '../SessionProviderLogo';
|
import SessionProviderLogo from '../../../SessionProviderLogo';
|
||||||
|
|
||||||
type SidebarSessionItemProps = {
|
type SidebarSessionItemProps = {
|
||||||
project: Project;
|
project: Project;
|
||||||
@@ -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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user