@@ -9,66 +9,75 @@ import { useActiveConversationStore } from "@/stores/useActiveConversationStore"
99import { runCommand } from "@/utils/runCommand" ;
1010import { useCodexStore } from "@/stores/useCodexStore" ;
1111
12+ const DEFAULT_DEV_URL = "http://localhost:3000" ;
13+
1214export const ChatToolbar : React . FC = ( ) => {
13- const { cwd } = useCodexStore ( )
15+ const { cwd } = useCodexStore ( ) ;
1416 const { showWebPreview, setWebPreviewUrl } = useLayoutStore ( ) ;
1517 const { currentFolder } = useFolderStore ( ) ;
1618 const { clearAll, requestFocus } = useChatInputStore ( ) ;
1719 const { setActiveConversationId, activeConversationId } = useActiveConversationStore ( ) ;
1820
19- const handleToggleWebPreview = async ( ) => {
21+ const handleNewConversation = React . useCallback ( ( ) => {
22+ setActiveConversationId ( null ) ;
23+ clearAll ( ) ;
24+ requestFocus ( ) ;
25+ } , [ setActiveConversationId , clearAll , requestFocus ] ) ;
26+
27+ const handleToggleWebPreview = React . useCallback ( async ( ) => {
2028 if ( showWebPreview ) {
2129 setWebPreviewUrl ( null ) ;
22- } else {
23- let defaultUrl = "http://localhost:3000" ;
30+ return ;
31+ }
32+
33+ let devUrl = DEFAULT_DEV_URL ;
2434
25- // Try to detect web framework and use appropriate URL
26- if ( currentFolder ) {
27- try {
28- const frameworkInfo = await detectWebFramework ( currentFolder ) ;
29- if ( frameworkInfo ) {
30- defaultUrl = frameworkInfo . devUrl ;
31- }
32- } catch ( error ) {
33- console . error ( "Failed to detect web framework:" , error ) ;
35+ if ( currentFolder ) {
36+ try {
37+ const frameworkInfo = await detectWebFramework ( currentFolder ) ;
38+ if ( frameworkInfo ) {
39+ devUrl = frameworkInfo . devUrl ;
3440 }
41+ } catch ( error ) {
42+ console . error ( "Failed to detect web framework:" , error ) ;
3543 }
44+ }
3645
37- setWebPreviewUrl ( defaultUrl ) ;
46+ setWebPreviewUrl ( devUrl ) ;
47+ } , [ showWebPreview , setWebPreviewUrl , currentFolder ] ) ;
48+
49+ const handleRunCommand = React . useCallback ( ( ) => {
50+ if ( activeConversationId ) {
51+ runCommand ( activeConversationId , cwd ) ;
3852 }
39- } ;
53+ } , [ activeConversationId , cwd ] ) ;
4054
55+ // Cmd/Ctrl+N shortcut for new conversation
4156 React . useEffect ( ( ) => {
4257 const handleShortcut = ( event : KeyboardEvent ) => {
4358 if ( ( event . metaKey || event . ctrlKey ) && event . key . toLowerCase ( ) === "n" ) {
4459 event . preventDefault ( ) ;
45- setActiveConversationId ( null ) ;
46- clearAll ( ) ;
47- requestFocus ( ) ;
60+ handleNewConversation ( ) ;
4861 }
4962 } ;
5063
5164 window . addEventListener ( "keydown" , handleShortcut ) ;
5265 return ( ) => window . removeEventListener ( "keydown" , handleShortcut ) ;
53- } , [ setActiveConversationId , clearAll , requestFocus ] ) ;
66+ } , [ handleNewConversation ] ) ;
5467
5568 return (
5669 < div className = "flex justify-between gap-2 px-2 w-full" >
5770 < span className = "flex gap-2" >
58- < Button
59- size = "icon"
60- onClick = { ( ) => {
61- setActiveConversationId ( null ) ;
62- clearAll ( ) ;
63- requestFocus ( ) ;
64- } }
65- >
71+ < Button size = "icon" onClick = { handleNewConversation } title = "New Conversation (Cmd/Ctrl+N)" >
6672 < PenSquare />
6773 </ Button >
74+
6875 < Button
6976 size = "icon"
70- variant = { "secondary" }
71- onClick = { ( ) => activeConversationId && runCommand ( activeConversationId , cwd ) }
77+ variant = "secondary"
78+ onClick = { handleRunCommand }
79+ disabled = { ! activeConversationId }
80+ title = "Run Command"
7281 >
7382 < Terminal />
7483 </ Button >
@@ -78,7 +87,7 @@ export const ChatToolbar: React.FC = () => {
7887 variant = "ghost"
7988 size = "icon"
8089 onClick = { handleToggleWebPreview }
81- className = { ` ${ showWebPreview ? "bg-accent" : "" } ` }
90+ className = { showWebPreview ? "bg-accent" : "" }
8291 title = "Toggle Web Preview"
8392 >
8493 < Globe />
0 commit comments