11import React , { useState , useEffect , useRef , useCallback } from 'react' ;
22import { io , Socket } from 'socket.io-client' ;
3- import { AnycodeEditorReact , AnycodeEditor , Edit , Operation } from 'anycode-react' ;
3+ import { AnycodeEditorReact , AnycodeEditor } from 'anycode-react' ;
44import type { Change , Position } from '../anycode-base/src/code' ;
5- import { WatcherCreate , WatcherEdits , WatcherRemove , type Cursor , type CursorHistory , type Terminal , type AcpSession , type AcpMessage , type AcpToolCall , type AcpPromptStateMessage } from './types' ;
6- import { loadTerminals , loadTerminalSelected , loadTerminalVisible , loadLeftPanelVisible , loadAcpPanelVisible } from './storage' ;
5+ import { WatcherCreate , WatcherEdits , WatcherRemove ,
6+ type CursorHistory , type Terminal , type AcpSession ,
7+ type AcpMessage , type AcpPromptStateMessage
8+ } from './types' ;
9+ import { loadTerminals , loadTerminalSelected , loadTerminalVisible ,
10+ loadLeftPanelVisible , loadAcpPanelVisible
11+ } from './storage' ;
712import { Allotment } from 'allotment' ;
813import 'allotment/dist/style.css' ;
9- import { TreeNodeComponent , TreeNode , FileState , TerminalComponent , TerminalTabs , AcpDialog , AgentSettingsDialog } from './components' ;
10- import { getAllAgents , getDefaultAgent , updateAgents , getDefaultAgentId , ensureDefaultAgents } from './agents' ;
14+ import { TreeNodeComponent , TreeNode , FileState , TerminalComponent ,
15+ TerminalTabs , AcpDialog
16+ } from './components' ;
17+ import { getAllAgents , getDefaultAgent , updateAgents , getDefaultAgentId ,
18+ ensureDefaultAgents
19+ } from './agents' ;
1120import { AcpAgent } from './types' ;
12- import { DEFAULT_FILE , DEFAULT_FILE_CONTENT , BACKEND_URL , MIN_LEFT_PANEL_SIZE , LANGUAGE_EXTENSIONS } from './constants' ;
21+ import { DEFAULT_FILE , DEFAULT_FILE_CONTENT , BACKEND_URL } from './constants' ;
1322import './App.css' ;
1423import {
1524 Completion , CompletionRequest , Diagnostic , DiagnosticResponse ,
1625 DefinitionRequest , DefinitionResponse
1726} from '../anycode-base/src/lsp' ;
27+ import { normalizePath , getFileName , getParentPath , joinPath ,
28+ getLanguageFromFileName
29+ } from './utils' ;
1830
1931const App : React . FC = ( ) => {
2032 console . log ( 'App rendered' ) ;
@@ -342,36 +354,10 @@ const App: React.FC = () => {
342354 const ws = io ( BACKEND_URL , { transports : [ 'websocket' ] } ) ;
343355 wsRef . current = ws ;
344356
345- ws . on ( 'connect' , ( ) => {
346- console . log ( 'Connected to backend' ) ;
347- setIsConnected ( true ) ;
348- setConnectionError ( null ) ;
349- reconnectAttemptsRef . current = 0 ;
350- openFolder ( '.' ) ;
351-
352- terminals . forEach ( term => {
353- console . log ( 'App: Initializing terminal:' , term . name ) ;
354- initializeTerminal ( term ) ;
355- reattachTerminalListener ( term . name ) ;
356- } ) ;
357-
358- // Reconnect to ACP agents
359- reconnectToAcpAgents ( ) ;
360- } ) ;
361- ws . on ( 'disconnect' , ( reason ) => {
362- console . log ( 'Disconnected from backend' , reason ) ;
363- setIsConnected ( false ) ;
364- attemptReconnect ( ) ;
365- } ) ;
366- ws . on ( 'connect_error' , ( error ) => {
367- console . error ( 'Socket connect error:' , error ) ;
368- setIsConnected ( false ) ;
369- setConnectionError ( 'Failed to connect to backend' ) ;
370- } ) ;
371- ws . on ( 'error' , ( data ) => {
372- console . error ( 'Backend error:' , data ) ;
373- setConnectionError ( data . message ) ;
374- } ) ;
357+ ws . on ( 'connect' , handleSocketConnect ) ;
358+ ws . on ( 'disconnect' , handleSocketDisconnect ) ;
359+ ws . on ( 'connect_error' , handleSocketConnectError ) ;
360+ ws . on ( 'error' , handleSocketError ) ;
375361 ws . on ( "lsp:diagnostics" , handleDiagnostics ) ;
376362 ws . on ( "watcher:edits" , handleWatcherEdits ) ;
377363 ws . on ( "watcher:create" , handleWatcherCreate ) ;
@@ -384,6 +370,39 @@ const App: React.FC = () => {
384370 }
385371 } ;
386372
373+ const handleSocketConnect = ( ) => {
374+ console . log ( 'Connected to backend' ) ;
375+ setIsConnected ( true ) ;
376+ setConnectionError ( null ) ;
377+ reconnectAttemptsRef . current = 0 ;
378+ openFolder ( '.' ) ;
379+
380+ terminals . forEach ( term => {
381+ console . log ( 'App: Initializing terminal:' , term . name ) ;
382+ initializeTerminal ( term ) ;
383+ reattachTerminalListener ( term . name ) ;
384+ } ) ;
385+
386+ reconnectToAcpAgents ( ) ;
387+ } ;
388+
389+ const handleSocketDisconnect = ( reason : string ) => {
390+ console . log ( 'Disconnected from backend' , reason ) ;
391+ setIsConnected ( false ) ;
392+ attemptReconnect ( ) ;
393+ } ;
394+
395+ const handleSocketConnectError = ( error : Error ) => {
396+ console . error ( 'Socket connect error:' , error ) ;
397+ setIsConnected ( false ) ;
398+ setConnectionError ( 'Failed to connect to backend' ) ;
399+ } ;
400+
401+ const handleSocketError = ( data : { message : string } ) => {
402+ console . error ( 'Backend error:' , data ) ;
403+ setConnectionError ( data . message ) ;
404+ } ;
405+
387406 const handleDiagnostics = ( diagnosticsResponse : DiagnosticResponse ) => {
388407 console . log ( "lsp:diagnostics" , diagnosticsResponse ) ;
389408
@@ -644,25 +663,20 @@ const App: React.FC = () => {
644663 } ;
645664
646665 const handleOpenFileResponse = ( path : string , content : string ) => {
647- const fileName = path . split ( '/' ) . pop ( ) || 'untitled' ;
666+ const fileName = getFileName ( path ) ;
648667 const language = getLanguageFromFileName ( fileName ) ;
649668 savedFileContentsRef . current . set ( path , content ) ;
650669 const newFile : FileState = { id : path , name : fileName , language } ;
651670 setFiles ( prev => [ ...prev , newFile ] ) ;
652671 setActiveFileId ( newFile . id ) ;
653672 } ;
654673
655- const getLanguageFromFileName = ( fileName : string ) : string => {
656- const ext = fileName . split ( '.' ) . pop ( ) ?. toLowerCase ( ) ;
657- return LANGUAGE_EXTENSIONS [ ext || '' ] || 'javascript' ;
658- } ;
659-
660674 const convertToTree = ( files : string [ ] , dirs : string [ ] , basePath : string ) : TreeNode [ ] => {
661675 const treeNodes : TreeNode [ ] = [ ] ;
662676
663677 // Add directories first
664678 dirs . forEach ( dirName => {
665- const dirPath = basePath === '.' ? dirName : ` ${ basePath } / ${ dirName } ` ;
679+ const dirPath = basePath === '.' ? dirName : joinPath ( basePath , dirName ) ;
666680 treeNodes . push ( {
667681 id : dirPath ,
668682 name : dirName ,
@@ -678,7 +692,7 @@ const App: React.FC = () => {
678692
679693 // Add files
680694 files . forEach ( fileName => {
681- const filePath = basePath === '.' ? fileName : ` ${ basePath } / ${ fileName } ` ;
695+ const filePath = basePath === '.' ? fileName : joinPath ( basePath , fileName ) ;
682696 treeNodes . push ( {
683697 id : filePath ,
684698 name : fileName ,
@@ -793,7 +807,7 @@ const App: React.FC = () => {
793807 const line = range . start . line ; const column = range . start . character ;
794808
795809 const filePath = uri . replace ( 'file://' , '' ) ;
796- const fileName = filePath . split ( '/' ) . pop ( ) || '' ;
810+ const fileName = getFileName ( filePath ) ;
797811
798812 pendingPositions . current . set ( filePath , { line, column } ) ;
799813
@@ -838,7 +852,7 @@ const App: React.FC = () => {
838852
839853 if ( prevPosition && prevPosition . file ) {
840854 const filePath = prevPosition . file ;
841- const fileName = filePath . split ( '/' ) . pop ( ) || '' ;
855+ const fileName = getFileName ( filePath ) ;
842856 const { line, column } = prevPosition . cursor ;
843857
844858 pendingPositions . current . set ( filePath , { line, column } ) ;
@@ -875,7 +889,7 @@ const App: React.FC = () => {
875889 const nextPosition = cursorHistory . current . redoStack . pop ( ) ;
876890 if ( nextPosition && nextPosition . file ) {
877891 const filePath = nextPosition . file ;
878- const fileName = filePath . split ( '/' ) . pop ( ) || '' ;
892+ const fileName = getFileName ( filePath ) ;
879893 const { line, column } = nextPosition . cursor ;
880894
881895 pendingPositions . current . set ( filePath , { line, column } ) ;
@@ -908,9 +922,8 @@ const App: React.FC = () => {
908922 const { path, isFile } = watcherCreate ;
909923
910924 // Extract parent path and filename
911- const parts = path . split ( '/' ) ;
912- const fileName = parts [ parts . length - 1 ] ;
913- const parentPath = parts . slice ( 0 , - 1 ) . join ( '/' ) || "." ;
925+ const fileName = getFileName ( path ) ;
926+ const parentPath = getParentPath ( path ) ;
914927
915928 setFileTree ( prevTree => {
916929 const addNode = ( nodes : TreeNode [ ] ) : TreeNode [ ] => {
@@ -1544,7 +1557,6 @@ const App: React.FC = () => {
15441557 { terminalContentPanel }
15451558 </ Allotment . Pane >
15461559 </ Allotment >
1547- { /* <div className="terminal-spacer"></div> */ }
15481560 </ div >
15491561 ) ;
15501562
@@ -1591,8 +1603,6 @@ const App: React.FC = () => {
15911603 </ div >
15921604 ) ) }
15931605 </ div >
1594-
1595- { /* <span className="language-indicator">{activeFile?.language.toUpperCase()}</span> */ }
15961606 </ div >
15971607 ) ;
15981608
@@ -1603,7 +1613,7 @@ const App: React.FC = () => {
16031613 < Allotment vertical = { true } defaultSizes = { [ 70 , 30 ] } separator = { true } onVisibleChange = { handleTerminalPanelVisibleChange } >
16041614 < Allotment . Pane >
16051615 < Allotment vertical = { false } defaultSizes = { [ 20 , 80 ] } separator = { false } onVisibleChange = { handleLeftPanelVisibleChange } >
1606- < Allotment . Pane snap visible = { leftPanelVisible } minSize = { MIN_LEFT_PANEL_SIZE } >
1616+ < Allotment . Pane snap visible = { leftPanelVisible } >
16071617 { fileTreePanel }
16081618 </ Allotment . Pane >
16091619 < Allotment . Pane snap >
0 commit comments