@@ -54,6 +54,14 @@ export interface ProjectContextType {
54
54
setRecentlyCompletedProjectId : ( id : string | null ) => void ;
55
55
chatId : string | null ;
56
56
setChatId : ( chatId : string | null ) => void ;
57
+ pendingProjects : Project [ ] ;
58
+ setPendingProjects : React . Dispatch < React . SetStateAction < Project [ ] > > ;
59
+ refetchPublicProjects : ( ) => Promise < any > ;
60
+ setRefetchPublicProjects : React . Dispatch <
61
+ React . SetStateAction < ( ) => Promise < any > >
62
+ > ;
63
+ tempLoadingProjectId : string | null ;
64
+ setTempLoadingProjectId : React . Dispatch < React . SetStateAction < string | null > > ;
57
65
}
58
66
59
67
export const ProjectContext = createContext < ProjectContextType | undefined > (
@@ -102,13 +110,14 @@ const checkUrlStatus = async (
102
110
103
111
export function ProjectProvider ( { children } : { children : ReactNode } ) {
104
112
const router = useRouter ( ) ;
105
- const { isAuthorized } = useAuthContext ( ) ;
113
+ const { isAuthorized, user } = useAuthContext ( ) ;
106
114
const [ projects , setProjects ] = useState < Project [ ] > ( [ ] ) ;
107
115
const [ curProject , setCurProject ] = useState < Project | undefined > ( undefined ) ;
108
116
const [ projectLoading , setProjectLoading ] = useState < boolean > ( true ) ;
109
117
const [ filePath , setFilePath ] = useState < string | null > ( null ) ;
110
118
const [ isLoading , setIsLoading ] = useState < boolean > ( false ) ;
111
119
const editorRef = useRef < any > ( null ) ;
120
+ const [ pendingProjects , setPendingProjects ] = useState < Project [ ] > ( [ ] ) ;
112
121
const [ recentlyCompletedProjectIdRaw , setRecentlyCompletedProjectIdRaw ] =
113
122
useState < string | null > ( ( ) =>
114
123
typeof window !== 'undefined'
@@ -128,6 +137,9 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
128
137
const [ chatId , setChatId ] = useState < string | null > ( null ) ;
129
138
const [ pollTime , setPollTime ] = useState ( Date . now ( ) ) ;
130
139
const [ isCreateButtonClicked , setIsCreateButtonClicked ] = useState ( false ) ;
140
+ const [ tempLoadingProjectId , setTempLoadingProjectId ] = useState <
141
+ string | null
142
+ > ( null ) ;
131
143
interface ChatProjectCacheEntry {
132
144
project : Project | null ;
133
145
timestamp : number ;
@@ -153,7 +165,9 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
153
165
const MAX_RETRIES = 30 ;
154
166
const CACHE_TTL = 5 * 60 * 1000 ; // 5 minutes TTL for cache
155
167
const SYNC_DEBOUNCE_TIME = 1000 ; // 1 second debounce for sync operations
156
-
168
+ const [ refetchPublicProjects , setRefetchPublicProjects ] = useState <
169
+ ( ) => Promise < any >
170
+ > ( ( ) => async ( ) => { } ) ;
157
171
// Mounted ref to prevent state updates after unmount
158
172
const isMounted = useRef ( true ) ;
159
173
@@ -710,18 +724,13 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
710
724
model = 'gpt-4o-mini'
711
725
) : Promise < string > => {
712
726
if ( ! prompt . trim ( ) ) {
713
- if ( isMounted . current ) {
714
- toast . error ( 'Please enter a project description' ) ;
715
- }
727
+ toast . error ( 'Please enter a project description' ) ;
716
728
throw new Error ( 'Invalid prompt' ) ;
717
729
}
718
730
719
731
try {
720
- if ( isMounted . current ) {
721
- setIsLoading ( true ) ;
722
- }
732
+ setIsLoading ( true ) ;
723
733
724
- // Default packages based on typical web project needs
725
734
const defaultPackages = [
726
735
{ name : 'react' , version : '^18.2.0' } ,
727
736
{ name : 'next' , version : '^13.4.0' } ,
@@ -734,32 +743,29 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
734
743
description : prompt ,
735
744
packages : defaultPackages ,
736
745
public : isPublic ,
737
- model : model ,
746
+ model,
738
747
} ,
739
748
} ,
740
749
} ) ;
750
+
741
751
const createdChat = result . data ?. createProject ;
742
752
if ( createdChat ?. id ) {
743
753
setChatId ( createdChat . id ) ;
744
754
setIsCreateButtonClicked ( true ) ;
745
755
localStorage . setItem ( 'pendingChatId' , createdChat . id ) ;
756
+ setTempLoadingProjectId ( createdChat . id ) ;
746
757
return createdChat . id ;
747
758
} else {
748
759
throw new Error ( 'Project creation failed: no chatId' ) ;
749
760
}
750
761
} catch ( error ) {
751
- logger . error ( 'Error creating project:' , error ) ;
752
- if ( isMounted . current ) {
753
- toast . error ( 'Failed to create project from prompt' ) ;
754
- }
762
+ toast . error ( 'Failed to create project from prompt' ) ;
755
763
throw error ;
756
764
} finally {
757
- if ( isMounted . current ) {
758
- setIsLoading ( false ) ;
759
- }
765
+ setIsLoading ( false ) ;
760
766
}
761
767
} ,
762
- [ createProject , setChatId ]
768
+ [ createProject , setChatId , user ]
763
769
) ;
764
770
765
771
// New function to fork a project
@@ -870,6 +876,30 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
870
876
retryCount : retries ,
871
877
} ) ;
872
878
879
+ // First update the project list to ensure it exists in allProjects
880
+ setProjects ( ( prev ) => {
881
+ const exists = prev . find ( ( p ) => p . id === project . id ) ;
882
+ return exists ? prev : [ ...prev , project ] ;
883
+ } ) ;
884
+
885
+ // Then more aggressively clean up pending projects
886
+ setPendingProjects ( ( prev ) => {
887
+ const filtered = prev . filter ( ( p ) => p . id !== project . id ) ;
888
+ if ( filtered . length !== prev . length ) {
889
+ logger . info (
890
+ `Removed project ${ project . id } from pending projects`
891
+ ) ;
892
+ }
893
+ return filtered ;
894
+ } ) ;
895
+
896
+ // Then trigger the public projects refetch
897
+ await refetchPublicProjects ( ) ;
898
+ console . log (
899
+ '[pollChatProject] refetchPublicProjects triggered after project is ready:' ,
900
+ project . id
901
+ ) ;
902
+
873
903
// Trigger state sync if needed
874
904
if (
875
905
now - projectSyncState . current . lastSyncTime >=
@@ -887,6 +917,9 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
887
917
} ) ;
888
918
}
889
919
920
+ if ( isMounted . current ) {
921
+ setTempLoadingProjectId ( null ) ;
922
+ }
890
923
return project ;
891
924
}
892
925
} catch ( error ) {
@@ -921,6 +954,7 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
921
954
MAX_RETRIES ,
922
955
CACHE_TTL ,
923
956
SYNC_DEBOUNCE_TIME ,
957
+ refetchPublicProjects ,
924
958
]
925
959
) ;
926
960
@@ -969,6 +1003,12 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
969
1003
setChatId,
970
1004
recentlyCompletedProjectId : recentlyCompletedProjectIdRaw ,
971
1005
setRecentlyCompletedProjectId,
1006
+ pendingProjects,
1007
+ setPendingProjects,
1008
+ refetchPublicProjects,
1009
+ setRefetchPublicProjects,
1010
+ tempLoadingProjectId,
1011
+ setTempLoadingProjectId,
972
1012
} ) ,
973
1013
[
974
1014
projects ,
@@ -988,6 +1028,12 @@ export function ProjectProvider({ children }: { children: ReactNode }) {
988
1028
chatId ,
989
1029
setChatId ,
990
1030
recentlyCompletedProjectIdRaw ,
1031
+ pendingProjects ,
1032
+ setPendingProjects ,
1033
+ refetchPublicProjects ,
1034
+ setRefetchPublicProjects ,
1035
+ tempLoadingProjectId ,
1036
+ setTempLoadingProjectId ,
991
1037
]
992
1038
) ;
993
1039
0 commit comments