11import { useTaskExecutionStore } from "@features/task-detail/stores/taskExecutionStore" ;
2+ import { trpcVanilla } from "@renderer/trpc/client" ;
23import { useTaskDirectoryStore } from "@stores/taskDirectoryStore" ;
34import { create } from "zustand" ;
45
@@ -26,6 +27,33 @@ interface CloneStore {
2627const REMOVE_DELAY_SUCCESS_MS = 3000 ;
2728const REMOVE_DELAY_ERROR_MS = 5000 ;
2829
30+ // Global subscription to clone progress events
31+ let globalSubscription : { unsubscribe : ( ) => void } | null = null ;
32+ let subscriptionRefCount = 0 ;
33+
34+ const ensureGlobalSubscription = ( store : CloneStore ) => {
35+ if ( globalSubscription ) {
36+ subscriptionRefCount ++ ;
37+ return ;
38+ }
39+
40+ subscriptionRefCount = 1 ;
41+ globalSubscription = trpcVanilla . git . onCloneProgress . subscribe ( undefined , {
42+ onData : ( event ) => {
43+ store . updateClone ( event . cloneId , event . status , event . message ) ;
44+ } ,
45+ } ) ;
46+ } ;
47+
48+ const releaseGlobalSubscription = ( ) => {
49+ subscriptionRefCount -- ;
50+ if ( subscriptionRefCount <= 0 && globalSubscription ) {
51+ globalSubscription . unsubscribe ( ) ;
52+ globalSubscription = null ;
53+ subscriptionRefCount = 0 ;
54+ }
55+ } ;
56+
2957export const cloneStore = create < CloneStore > ( ( set , get ) => {
3058 const updateTaskRepoExists = ( targetPath : string , exists : boolean ) => {
3159 const taskStore = useTaskExecutionStore . getState ( ) ;
@@ -66,26 +94,14 @@ export const cloneStore = create<CloneStore>((set, get) => {
6694 window . setTimeout ( ( ) => get ( ) . removeClone ( cloneId ) , REMOVE_DELAY_ERROR_MS ) ;
6795 } ;
6896
69- return {
97+ const store : CloneStore = {
7098 operations : { } ,
7199
72100 startClone : ( cloneId , repository , targetPath ) => {
73- const unsubscribe = window . electronAPI . onCloneProgress (
74- cloneId ,
75- ( event ) => {
76- get ( ) . updateClone ( cloneId , event . status , event . message ) ;
77-
78- const operation = get ( ) . operations [ cloneId ] ;
79- if ( ! operation ) return ;
80-
81- if ( event . status === "complete" ) {
82- handleComplete ( cloneId , repository ) ;
83- } else if ( event . status === "error" ) {
84- handleError ( cloneId , repository , event . message ) ;
85- }
86- } ,
87- ) ;
101+ // Ensure global subscription is active
102+ ensureGlobalSubscription ( store ) ;
88103
104+ // Set up clone operation with progress handler
89105 set ( ( state ) => ( {
90106 operations : {
91107 ...state . operations ,
@@ -95,10 +111,22 @@ export const cloneStore = create<CloneStore>((set, get) => {
95111 targetPath,
96112 status : "cloning" ,
97113 latestMessage : `Cloning ${ repository } ...` ,
98- unsubscribe,
114+ unsubscribe : releaseGlobalSubscription ,
99115 } ,
100116 } ,
101117 } ) ) ;
118+
119+ // Start the clone operation via tRPC mutation
120+ trpcVanilla . git . cloneRepository
121+ . mutate ( { repoUrl : repository , targetPath, cloneId } )
122+ . then ( ( ) => {
123+ handleComplete ( cloneId , repository ) ;
124+ } )
125+ . catch ( ( err ) => {
126+ const message = err instanceof Error ? err . message : "Clone failed" ;
127+ get ( ) . updateClone ( cloneId , "error" , message ) ;
128+ handleError ( cloneId , repository , message ) ;
129+ } ) ;
102130 } ,
103131
104132 updateClone : ( cloneId , status , message ) => {
@@ -140,4 +168,6 @@ export const cloneStore = create<CloneStore>((set, get) => {
140168 ( op ) => op . repository === repository ,
141169 ) ?? null ,
142170 } ;
171+
172+ return store ;
143173} ) ;
0 commit comments