@@ -752,9 +752,7 @@ export default function Sidebar() {
752752 "This permanently clears conversation history for this thread." ,
753753 ] . join ( "\n" ) ,
754754 ) ;
755- if ( ! confirmed ) {
756- return ;
757- }
755+ if ( ! confirmed ) return ;
758756 }
759757 await deleteThread ( threadId ) ;
760758 } ,
@@ -821,6 +819,37 @@ export default function Sidebar() {
821819 ] ,
822820 ) ;
823821
822+ const removeProject = useCallback (
823+ async ( projectId : ProjectId ) : Promise < void > => {
824+ const api = readNativeApi ( ) ;
825+ if ( ! api ) return ;
826+ const project = projects . find ( ( entry ) => entry . id === projectId ) ;
827+ if ( ! project ) return ;
828+
829+ try {
830+ const projectDraftThread = getDraftThreadByProjectId ( projectId ) ;
831+ if ( projectDraftThread ) {
832+ clearComposerDraftForThread ( projectDraftThread . threadId ) ;
833+ }
834+ clearProjectDraftThreadId ( projectId ) ;
835+ await api . orchestration . dispatchCommand ( {
836+ type : "project.delete" ,
837+ commandId : newCommandId ( ) ,
838+ projectId,
839+ } ) ;
840+ } catch ( error ) {
841+ const message = error instanceof Error ? error . message : "Unknown error removing project." ;
842+ console . error ( "Failed to remove project" , { projectId, error } ) ;
843+ toastManager . add ( {
844+ type : "error" ,
845+ title : `Failed to remove "${ project . name } "` ,
846+ description : message ,
847+ } ) ;
848+ }
849+ } ,
850+ [ clearComposerDraftForThread , clearProjectDraftThreadId , getDraftThreadByProjectId , projects ] ,
851+ ) ;
852+
824853 const handleThreadClick = useCallback (
825854 ( event : MouseEvent , threadId : ThreadId , orderedProjectThreadIds : readonly ThreadId [ ] ) => {
826855 const isMac = isMacPlatform ( navigator . platform ) ;
@@ -874,45 +903,59 @@ export default function Sidebar() {
874903
875904 const projectThreads = threads . filter ( ( thread ) => thread . projectId === projectId ) ;
876905 if ( projectThreads . length > 0 ) {
877- toastManager . add ( {
906+ const warningToastId = toastManager . add ( {
878907 type : "warning" ,
879908 title : "Project is not empty" ,
880909 description : "Delete all threads in this project before removing it." ,
910+ data : {
911+ actionLayout : "stacked-end" ,
912+ actionVariant : "destructive" ,
913+ } ,
914+ actionProps : {
915+ children : "Delete anyway" ,
916+ onClick : ( ) => {
917+ void ( async ( ) => {
918+ toastManager . close ( warningToastId ) ;
919+ await new Promise < void > ( ( resolve ) => {
920+ window . setTimeout ( resolve , 180 ) ;
921+ } ) ;
922+ const confirmed = await api . dialogs . confirm (
923+ [
924+ `Remove project "${ project . name } " and delete its ${ projectThreads . length } thread${
925+ projectThreads . length === 1 ? "" : "s"
926+ } ?`,
927+ "This will permanently clear conversation history for those threads." ,
928+ "This action cannot be undone." ,
929+ ] . join ( "\n" ) ,
930+ ) ;
931+ if ( ! confirmed ) return ;
932+
933+ const deletedThreadIds = new Set < ThreadId > (
934+ projectThreads . map ( ( thread ) => thread . id ) ,
935+ ) ;
936+ for ( const thread of projectThreads ) {
937+ await deleteThread ( thread . id , { deletedThreadIds } ) ;
938+ }
939+ await removeProject ( projectId ) ;
940+ } ) ( ) . catch ( ( error ) => {
941+ toastManager . add ( {
942+ type : "error" ,
943+ title : `Failed to remove "${ project . name } "` ,
944+ description :
945+ error instanceof Error ? error . message : "Unknown error removing project." ,
946+ } ) ;
947+ } ) ;
948+ } ,
949+ } ,
881950 } ) ;
882951 return ;
883952 }
884953
885954 const confirmed = await api . dialogs . confirm ( `Remove project "${ project . name } "?` ) ;
886955 if ( ! confirmed ) return ;
887-
888- try {
889- const projectDraftThread = getDraftThreadByProjectId ( projectId ) ;
890- if ( projectDraftThread ) {
891- clearComposerDraftForThread ( projectDraftThread . threadId ) ;
892- }
893- clearProjectDraftThreadId ( projectId ) ;
894- await api . orchestration . dispatchCommand ( {
895- type : "project.delete" ,
896- commandId : newCommandId ( ) ,
897- projectId,
898- } ) ;
899- } catch ( error ) {
900- const message = error instanceof Error ? error . message : "Unknown error removing project." ;
901- console . error ( "Failed to remove project" , { projectId, error } ) ;
902- toastManager . add ( {
903- type : "error" ,
904- title : `Failed to remove "${ project . name } "` ,
905- description : message ,
906- } ) ;
907- }
956+ await removeProject ( projectId ) ;
908957 } ,
909- [
910- clearComposerDraftForThread ,
911- clearProjectDraftThreadId ,
912- getDraftThreadByProjectId ,
913- projects ,
914- threads ,
915- ] ,
958+ [ deleteThread , projects , removeProject , threads ] ,
916959 ) ;
917960
918961 const projectDnDSensors = useSensors (
0 commit comments