@@ -31,6 +31,7 @@ export type ReplSaveContextType = {
3131  isDirty : boolean 
3232  isEffectivelyDirty : boolean 
3333  isSaving : boolean 
34+   isForking : boolean 
3435  allowSave : boolean 
3536  allowFork : boolean 
3637} 
@@ -48,6 +49,7 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
4849  const  {  flushPendingChanges }  =  useWritableModels ( ) 
4950  const  [ savedState ,  setSavedState ]  =  useReplSavedState ( ) 
5051  const  [ isSaving ,  setIsSaving ]  =  useState ( false ) 
52+   const  [ isForking ,  setIsForking ]  =  useState ( false ) 
5153
5254  const  formatOnSave  =  useMemo ( 
5355    ( )  =>  userStoredState . workbench . formatOnSave , 
@@ -67,18 +69,18 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
6769  const  isDirty  =  useMemo < boolean > ( ( )  =>  checkDirty ( state ,  savedState ) ,  [ state ,  savedState ] ) 
6870
6971  const  allowSave  =  useMemo < boolean > ( 
70-     ( )  =>  ! isSaving  &&  ( isNew  ||  isDirty ) , 
71-     [ isSaving ,  isNew ,  isDirty ] 
72+     ( )  =>  ! isSaving  &&  ! isForking   &&   ( isNew  ||  isEffectivelyDirty ) , 
73+     [ isSaving ,  isForking ,   isNew ,  isEffectivelyDirty ] 
7274  ) 
7375
74-   const  allowFork  =  useMemo < boolean > ( ( )  =>  ! isSaving  &&  ! isNew ,  [ isSaving ,  isNew ] ) 
76+   const  allowFork  =  useMemo < boolean > ( ( )  =>  ! isForking  &&  ! isNew ,  [ isForking ,  isNew ] ) 
7577
7678  useEffect ( ( )  =>  { 
7779    stateRef . current  =  state 
7880  } ,  [ state ] ) 
7981
80-   const  handleSaveError  =  useCallback ( 
81-     async  ( error : unknown )  =>  { 
82+   const  handleSaveOrForkError  =  useCallback ( 
83+     async  ( type :  'save'   |   'fork' ,   error : unknown )  =>  { 
8284      const  isAborted  =  isAbortError ( error  instanceof  ResponseError  ? error . cause  : error ) 
8385      if  ( isAborted )  { 
8486        return 
@@ -88,21 +90,26 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
8890
8991      if  ( error  instanceof  ResponseError )  { 
9092        if  ( error . status  ===  401 )  { 
91-           toast . info ( 'Please sign in to save your changes.' ,  { 
92-             action : { 
93-               label : 'Sign in with Github' , 
94-               onClick : ( )  =>  { 
95-                 signInWithGithub ( {  popup : true  } ) 
93+           toast . info ( 
94+             type  ===  'save' 
95+               ? 'Please sign in to save your changes.' 
96+               : 'Please sign in to fork this REPL.' , 
97+             { 
98+               action : { 
99+                 label : 'Sign in with Github' , 
100+                 onClick : ( )  =>  { 
101+                   signInWithGithub ( {  popup : true  } ) 
102+                 } , 
96103              } , 
97-             } , 
98-           } ) 
104+             } 
105+           ) 
99106        }  else  { 
100107          toast . error ( error . message ,  { 
101108            description : `${ error . status } ${ error . statusText } ${ error . cause  ??  'Something went wrong :(' }  , 
102109          } ) 
103110        } 
104111      }  else  { 
105-         toast . error ( ' Failed to save' ,  { 
112+         toast . error ( ` Failed to ${ type } ` ,  { 
106113          description : error  instanceof  Error  ? error . message  : 'Unknown error' , 
107114        } ) 
108115      } 
@@ -123,7 +130,7 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
123130
124131        return  await  callback ( {  signal } ) 
125132      }  catch  ( error )  { 
126-         handleSaveError ( error ) 
133+         handleSaveOrForkError ( 'save' ,   error ) 
127134        return  false 
128135      }  finally  { 
129136        if  ( signal  ===  abortControllerRef . current ?. signal )  { 
@@ -132,7 +139,32 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
132139        } 
133140      } 
134141    } , 
135-     [ handleSaveError ] 
142+     [ handleSaveOrForkError ] 
143+   ) 
144+ 
145+   const  forkWrapper  =  useCallback ( 
146+     async  ( callback : ( args : {  signal : AbortSignal  } )  =>  Promise < boolean > )  =>  { 
147+       let  signal : AbortSignal  |  null  =  null 
148+ 
149+       try  { 
150+         setIsForking ( true ) 
151+ 
152+         abortControllerRef . current ?. abort ( ) 
153+         abortControllerRef . current  =  new  AbortController ( ) 
154+         signal  =  abortControllerRef . current . signal 
155+ 
156+         return  await  callback ( {  signal } ) 
157+       }  catch  ( error )  { 
158+         handleSaveOrForkError ( 'fork' ,  error ) 
159+         return  false 
160+       }  finally  { 
161+         if  ( signal  ===  abortControllerRef . current ?. signal )  { 
162+           setIsForking ( false ) 
163+           abortControllerRef . current  =  null 
164+         } 
165+       } 
166+     } , 
167+     [ handleSaveOrForkError ] 
136168  ) 
137169
138170  const  saveState  =  useCallback < ( )  =>  Promise < boolean > > ( async  ( )  =>  { 
@@ -229,7 +261,7 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
229261  ] ) 
230262
231263  const  forkState  =  useCallback < ( )  =>  Promise < boolean > > ( async  ( )  =>  { 
232-     return  await  saveWrapper ( forkFn ) 
264+     return  await  forkWrapper ( forkFn ) 
233265
234266    async  function  forkFn ( {  signal } : {  signal : AbortSignal  } )  { 
235267      if  ( ! user )  { 
@@ -280,7 +312,7 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
280312    user , 
281313    setState , 
282314    setSavedState , 
283-     saveWrapper , 
315+     forkWrapper , 
284316    signInWithGithub , 
285317    queryClient , 
286318    supabase , 
@@ -296,6 +328,7 @@ export default function ReplSaveProvider({ children }: { children: React.ReactNo
296328        isEffectivelyDirty, 
297329        isDirty, 
298330        isSaving, 
331+         isForking, 
299332        allowSave, 
300333        allowFork, 
301334      } } 
0 commit comments