@@ -1074,9 +1074,7 @@ export default function Sidebar() {
10741074 "This permanently clears conversation history for this thread." ,
10751075 ] . join ( "\n" ) ,
10761076 ) ;
1077- if ( ! confirmed ) {
1078- return ;
1079- }
1077+ if ( ! confirmed ) return ;
10801078 }
10811079 await deleteThread ( threadId ) ;
10821080 } ,
@@ -1145,6 +1143,37 @@ export default function Sidebar() {
11451143 ] ,
11461144 ) ;
11471145
1146+ const removeProject = useCallback (
1147+ async ( projectId : ProjectId ) : Promise < void > => {
1148+ const api = readNativeApi ( ) ;
1149+ if ( ! api ) return ;
1150+ const project = projects . find ( ( entry ) => entry . id === projectId ) ;
1151+ if ( ! project ) return ;
1152+
1153+ try {
1154+ const projectDraftThread = getDraftThreadByProjectId ( projectId ) ;
1155+ if ( projectDraftThread ) {
1156+ clearComposerDraftForThread ( projectDraftThread . threadId ) ;
1157+ }
1158+ clearProjectDraftThreadId ( projectId ) ;
1159+ await api . orchestration . dispatchCommand ( {
1160+ type : "project.delete" ,
1161+ commandId : newCommandId ( ) ,
1162+ projectId,
1163+ } ) ;
1164+ } catch ( error ) {
1165+ const message = error instanceof Error ? error . message : "Unknown error removing project." ;
1166+ console . error ( "Failed to remove project" , { projectId, error } ) ;
1167+ toastManager . add ( {
1168+ type : "error" ,
1169+ title : `Failed to remove "${ project . name } "` ,
1170+ description : message ,
1171+ } ) ;
1172+ }
1173+ } ,
1174+ [ clearComposerDraftForThread , clearProjectDraftThreadId , getDraftThreadByProjectId , projects ] ,
1175+ ) ;
1176+
11481177 const handleThreadClick = useCallback (
11491178 ( event : MouseEvent , threadId : ThreadId , orderedProjectThreadIds : readonly ThreadId [ ] ) => {
11501179 const isMac = isMacPlatform ( navigator . platform ) ;
@@ -1219,46 +1248,57 @@ export default function Sidebar() {
12191248
12201249 const projectThreadIds = threadIdsByProjectId [ projectId ] ?? [ ] ;
12211250 if ( projectThreadIds . length > 0 ) {
1222- toastManager . add ( {
1251+ const warningToastId = toastManager . add ( {
12231252 type : "warning" ,
12241253 title : "Project is not empty" ,
12251254 description : "Delete all threads in this project before removing it." ,
1255+ data : {
1256+ actionLayout : "stacked-end" ,
1257+ actionVariant : "destructive" ,
1258+ } ,
1259+ actionProps : {
1260+ children : "Delete anyway" ,
1261+ onClick : ( ) => {
1262+ void ( async ( ) => {
1263+ toastManager . close ( warningToastId ) ;
1264+ await new Promise < void > ( ( resolve ) => {
1265+ window . setTimeout ( resolve , 180 ) ;
1266+ } ) ;
1267+ const confirmed = await api . dialogs . confirm (
1268+ [
1269+ `Remove project "${ project . name } " and delete its ${ projectThreadIds . length } thread${
1270+ projectThreadIds . length === 1 ? "" : "s"
1271+ } ?`,
1272+ "This will permanently clear conversation history for those threads." ,
1273+ "This action cannot be undone." ,
1274+ ] . join ( "\n" ) ,
1275+ ) ;
1276+ if ( ! confirmed ) return ;
1277+
1278+ const deletedThreadIds = new Set < ThreadId > ( projectThreadIds ) ;
1279+ for ( const threadId of projectThreadIds ) {
1280+ await deleteThread ( threadId , { deletedThreadIds } ) ;
1281+ }
1282+ await removeProject ( projectId ) ;
1283+ } ) ( ) . catch ( ( error ) => {
1284+ toastManager . add ( {
1285+ type : "error" ,
1286+ title : `Failed to remove "${ project . name } "` ,
1287+ description :
1288+ error instanceof Error ? error . message : "Unknown error removing project." ,
1289+ } ) ;
1290+ } ) ;
1291+ } ,
1292+ } ,
12261293 } ) ;
12271294 return ;
12281295 }
12291296
12301297 const confirmed = await api . dialogs . confirm ( `Remove project "${ project . name } "?` ) ;
12311298 if ( ! confirmed ) return ;
1232-
1233- try {
1234- const projectDraftThread = getDraftThreadByProjectId ( projectId ) ;
1235- if ( projectDraftThread ) {
1236- clearComposerDraftForThread ( projectDraftThread . threadId ) ;
1237- }
1238- clearProjectDraftThreadId ( projectId ) ;
1239- await api . orchestration . dispatchCommand ( {
1240- type : "project.delete" ,
1241- commandId : newCommandId ( ) ,
1242- projectId,
1243- } ) ;
1244- } catch ( error ) {
1245- const message = error instanceof Error ? error . message : "Unknown error removing project." ;
1246- console . error ( "Failed to remove project" , { projectId, error } ) ;
1247- toastManager . add ( {
1248- type : "error" ,
1249- title : `Failed to remove "${ project . name } "` ,
1250- description : message ,
1251- } ) ;
1252- }
1299+ await removeProject ( projectId ) ;
12531300 } ,
1254- [
1255- clearComposerDraftForThread ,
1256- clearProjectDraftThreadId ,
1257- copyPathToClipboard ,
1258- getDraftThreadByProjectId ,
1259- projects ,
1260- threadIdsByProjectId ,
1261- ] ,
1301+ [ copyPathToClipboard , deleteThread , projects , removeProject , threadIdsByProjectId ] ,
12621302 ) ;
12631303
12641304 const projectDnDSensors = useSensors (
0 commit comments