@@ -13,14 +13,47 @@ import {
1313import { useSettings } from "@/hooks/useSettings" ;
1414import type { ChatMode } from "@/lib/schemas" ;
1515import { cn } from "@/lib/utils" ;
16+ import { IpcClient } from "@/ipc/ipc_client" ;
17+ import { showError } from "@/lib/toast" ;
18+ import { useState } from "react" ;
19+ import { Loader2 } from "lucide-react" ;
1620
17- export function ChatModeSelector ( ) {
21+ export function ChatModeSelector ( { appId } : { appId ?: number } ) {
1822 const { settings, updateSettings } = useSettings ( ) ;
23+ const [ isCreatingFolder , setIsCreatingFolder ] = useState ( false ) ;
1924
2025 const selectedMode = settings ?. selectedChatMode || "build" ;
2126
22- const handleModeChange = ( value : string ) => {
23- updateSettings ( { selectedChatMode : value as ChatMode } ) ;
27+ const handleModeChange = async ( value : string ) => {
28+ const newMode = value as ChatMode ;
29+
30+ // If switching to backend mode and we have an app ID, check if backend folder exists
31+ if ( newMode === "backend" && appId ) {
32+ try {
33+ setIsCreatingFolder ( true ) ;
34+ // Get the app to check its structure
35+ const app = await IpcClient . getInstance ( ) . getApp ( appId ) ;
36+ const backendFiles = app . files . filter ( ( file : string ) => file . startsWith ( "backend/" ) ) ;
37+
38+ // If no backend files exist, create the backend folder
39+ if ( backendFiles . length === 0 ) {
40+ await IpcClient . getInstance ( ) . invoke ( "create-missing-folder" , {
41+ appId,
42+ folderType : "backend" ,
43+ backendFramework : settings ?. selectedBackendFramework ,
44+ } ) ;
45+ }
46+ } catch ( error ) {
47+ console . error ( "Error creating backend folder:" , error ) ;
48+ showError ( error ) ;
49+ return ; // Don't change the mode if folder creation failed
50+ } finally {
51+ setIsCreatingFolder ( false ) ;
52+ }
53+ }
54+
55+ // Update the chat mode
56+ updateSettings ( { selectedChatMode : newMode } ) ;
2457 } ;
2558
2659 const getModeDisplayName = ( mode : ChatMode ) => {
@@ -29,13 +62,15 @@ export function ChatModeSelector() {
2962 return "Build" ;
3063 case "ask" :
3164 return "Ask" ;
65+ case "backend" :
66+ return "Backend" ;
3267 default :
3368 return "Build" ;
3469 }
3570 } ;
3671
3772 return (
38- < Select value = { selectedMode } onValueChange = { handleModeChange } >
73+ < Select value = { selectedMode } onValueChange = { handleModeChange } disabled = { isCreatingFolder } >
3974 < Tooltip >
4075 < TooltipTrigger asChild >
4176 < MiniSelectTrigger
@@ -48,10 +83,19 @@ export function ChatModeSelector() {
4883 ) }
4984 size = "sm"
5085 >
51- < SelectValue > { getModeDisplayName ( selectedMode ) } </ SelectValue >
86+ { isCreatingFolder ? (
87+ < div className = "flex items-center gap-1" >
88+ < Loader2 size = { 12 } className = "animate-spin" />
89+ < span > Creating...</ span >
90+ </ div >
91+ ) : (
92+ < SelectValue > { getModeDisplayName ( selectedMode ) } </ SelectValue >
93+ ) }
5294 </ MiniSelectTrigger >
5395 </ TooltipTrigger >
54- < TooltipContent > Open mode menu</ TooltipContent >
96+ < TooltipContent >
97+ { isCreatingFolder ? "Creating backend folder..." : "Open mode menu" }
98+ </ TooltipContent >
5599 </ Tooltip >
56100 < SelectContent align = "start" onCloseAutoFocus = { ( e ) => e . preventDefault ( ) } >
57101 < SelectItem value = "build" >
@@ -70,6 +114,14 @@ export function ChatModeSelector() {
70114 </ span >
71115 </ div >
72116 </ SelectItem >
117+ < SelectItem value = "backend" >
118+ < div className = "flex flex-col items-start" >
119+ < span className = "font-medium" > Backend</ span >
120+ < span className = "text-xs text-muted-foreground" >
121+ Backend development with Roo-Code
122+ </ span >
123+ </ div >
124+ </ SelectItem >
73125 </ SelectContent >
74126 </ Select >
75127 ) ;
0 commit comments