@cerbur/clutch-dsh-worktree 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (501) hide show
  1. package/README.md +99 -23
  2. package/README.zh.md +75 -19
  3. package/lib/client/WorktreeSurface.d.ts +4 -7
  4. package/lib/client/WorktreeSurface.d.ts.map +1 -1
  5. package/lib/client/WorktreeSurface.js +44 -1419
  6. package/lib/client/WorktreeSurface.js.map +1 -1
  7. package/lib/client/{WorktreeContext.d.ts → context/WorktreeContext.d.ts} +1 -1
  8. package/lib/client/context/WorktreeContext.d.ts.map +1 -0
  9. package/lib/client/context/WorktreeContext.js.map +1 -0
  10. package/lib/client/{WorktreeHeroContext.d.ts → context/WorktreeHeroContext.d.ts} +1 -1
  11. package/lib/client/context/WorktreeHeroContext.d.ts.map +1 -0
  12. package/lib/client/context/WorktreeHeroContext.js.map +1 -0
  13. package/lib/client/{worktree-context-store.d.ts → context/worktree-context-store.d.ts} +1 -1
  14. package/lib/client/context/worktree-context-store.d.ts.map +1 -0
  15. package/lib/client/{worktree-context-store.js → context/worktree-context-store.js} +2 -2
  16. package/lib/client/context/worktree-context-store.js.map +1 -0
  17. package/lib/client/{worktree-context.d.ts → context/worktree-context.d.ts} +1 -1
  18. package/lib/client/context/worktree-context.d.ts.map +1 -0
  19. package/lib/client/{worktree-context.js → context/worktree-context.js} +5 -3
  20. package/lib/client/context/worktree-context.js.map +1 -0
  21. package/lib/client/entry.d.ts +1 -1
  22. package/lib/client/entry.d.ts.map +1 -1
  23. package/lib/client/entry.js +25 -13
  24. package/lib/client/entry.js.map +1 -1
  25. package/lib/client/index.d.ts +3 -3
  26. package/lib/client/index.d.ts.map +1 -1
  27. package/lib/client/index.js +2 -2
  28. package/lib/client/index.js.map +1 -1
  29. package/lib/client/locales.d.ts +66 -0
  30. package/lib/client/locales.d.ts.map +1 -1
  31. package/lib/client/locales.js +76 -10
  32. package/lib/client/locales.js.map +1 -1
  33. package/lib/client/{WorktreeOverlay.d.ts → overlay/WorktreeOverlay.d.ts} +2 -2
  34. package/lib/client/overlay/WorktreeOverlay.d.ts.map +1 -0
  35. package/lib/client/{WorktreeOverlay.js → overlay/WorktreeOverlay.js} +2 -2
  36. package/lib/client/overlay/WorktreeOverlay.js.map +1 -0
  37. package/lib/client/overlay/overlay-bounds.d.ts.map +1 -0
  38. package/lib/client/overlay/overlay-bounds.js.map +1 -0
  39. package/lib/client/overlay/sidebar-overlay-geometry.d.ts.map +1 -0
  40. package/lib/client/overlay/sidebar-overlay-geometry.js.map +1 -0
  41. package/lib/client/permission/worktree-permission-icon.d.ts.map +1 -0
  42. package/lib/client/permission/worktree-permission-icon.js.map +1 -0
  43. package/lib/client/permission/worktree-permission.d.ts.map +1 -0
  44. package/lib/client/permission/worktree-permission.js.map +1 -0
  45. package/lib/client/session/session-view.d.ts.map +1 -0
  46. package/lib/client/session/session-view.js.map +1 -0
  47. package/lib/client/{virtual-workspace-membership.d.ts → session/virtual-workspace-membership.d.ts} +1 -1
  48. package/lib/client/session/virtual-workspace-membership.d.ts.map +1 -0
  49. package/lib/client/{virtual-workspace-membership.js → session/virtual-workspace-membership.js} +1 -1
  50. package/lib/client/session/virtual-workspace-membership.js.map +1 -0
  51. package/lib/client/{worktree-session-fork.d.ts → session/worktree-session-fork.d.ts} +7 -1
  52. package/lib/client/session/worktree-session-fork.d.ts.map +1 -0
  53. package/lib/client/{worktree-session-fork.js → session/worktree-session-fork.js} +50 -4
  54. package/lib/client/session/worktree-session-fork.js.map +1 -0
  55. package/lib/client/session/worktree-session-order.d.ts.map +1 -0
  56. package/lib/client/session/worktree-session-order.js.map +1 -0
  57. package/lib/client/session/worktree-session-position.d.ts.map +1 -0
  58. package/lib/client/session/worktree-session-position.js.map +1 -0
  59. package/lib/client/{worktree-session.d.ts → session/worktree-session.d.ts} +3 -3
  60. package/lib/client/session/worktree-session.d.ts.map +1 -0
  61. package/lib/client/{worktree-session.js → session/worktree-session.js} +3 -3
  62. package/lib/client/session/worktree-session.js.map +1 -0
  63. package/lib/client/surface/actions/lifecycle-commands.d.ts +9 -0
  64. package/lib/client/surface/actions/lifecycle-commands.d.ts.map +1 -0
  65. package/lib/client/surface/actions/lifecycle-commands.js +243 -0
  66. package/lib/client/surface/actions/lifecycle-commands.js.map +1 -0
  67. package/lib/client/surface/actions/useDragActions.d.ts +26 -0
  68. package/lib/client/surface/actions/useDragActions.d.ts.map +1 -0
  69. package/lib/client/surface/actions/useDragActions.js +125 -0
  70. package/lib/client/surface/actions/useDragActions.js.map +1 -0
  71. package/lib/client/surface/actions/useLifecycleActions.d.ts +30 -0
  72. package/lib/client/surface/actions/useLifecycleActions.d.ts.map +1 -0
  73. package/lib/client/surface/actions/useLifecycleActions.js +140 -0
  74. package/lib/client/surface/actions/useLifecycleActions.js.map +1 -0
  75. package/lib/client/surface/actions/useNativeActions.d.ts +48 -0
  76. package/lib/client/surface/actions/useNativeActions.d.ts.map +1 -0
  77. package/lib/client/surface/actions/useNativeActions.js +182 -0
  78. package/lib/client/surface/actions/useNativeActions.js.map +1 -0
  79. package/lib/client/surface/actions/useSessionActions.d.ts +24 -0
  80. package/lib/client/surface/actions/useSessionActions.d.ts.map +1 -0
  81. package/lib/client/surface/actions/useSessionActions.js +116 -0
  82. package/lib/client/surface/actions/useSessionActions.js.map +1 -0
  83. package/lib/client/surface/actions/useSurfaceMutation.d.ts +15 -0
  84. package/lib/client/surface/actions/useSurfaceMutation.d.ts.map +1 -0
  85. package/lib/client/surface/actions/useSurfaceMutation.js +24 -0
  86. package/lib/client/surface/actions/useSurfaceMutation.js.map +1 -0
  87. package/lib/client/surface/actions/useWorktreeRegistration.d.ts +31 -0
  88. package/lib/client/surface/actions/useWorktreeRegistration.d.ts.map +1 -0
  89. package/lib/client/surface/actions/useWorktreeRegistration.js +203 -0
  90. package/lib/client/surface/actions/useWorktreeRegistration.js.map +1 -0
  91. package/lib/client/surface/actions/worktree-cleanup-flow.d.ts +10 -0
  92. package/lib/client/surface/actions/worktree-cleanup-flow.d.ts.map +1 -0
  93. package/lib/client/surface/actions/worktree-cleanup-flow.js +19 -0
  94. package/lib/client/surface/actions/worktree-cleanup-flow.js.map +1 -0
  95. package/lib/client/surface/components/AccessConfirmation.d.ts +9 -0
  96. package/lib/client/surface/components/AccessConfirmation.d.ts.map +1 -0
  97. package/lib/client/surface/components/AccessConfirmation.js +18 -0
  98. package/lib/client/surface/components/AccessConfirmation.js.map +1 -0
  99. package/lib/client/surface/components/ActiveWorktree.d.ts +28 -0
  100. package/lib/client/surface/components/ActiveWorktree.d.ts.map +1 -0
  101. package/lib/client/surface/components/ActiveWorktree.js +154 -0
  102. package/lib/client/surface/components/ActiveWorktree.js.map +1 -0
  103. package/lib/client/surface/components/ArchivedWorktree.d.ts +24 -0
  104. package/lib/client/surface/components/ArchivedWorktree.d.ts.map +1 -0
  105. package/lib/client/surface/components/ArchivedWorktree.js +145 -0
  106. package/lib/client/surface/components/ArchivedWorktree.js.map +1 -0
  107. package/lib/client/surface/components/ArchivedWorktrees.d.ts +25 -0
  108. package/lib/client/surface/components/ArchivedWorktrees.d.ts.map +1 -0
  109. package/lib/client/surface/components/ArchivedWorktrees.js +20 -0
  110. package/lib/client/surface/components/ArchivedWorktrees.js.map +1 -0
  111. package/lib/client/surface/components/LifecycleDialogs.d.ts +20 -0
  112. package/lib/client/surface/components/LifecycleDialogs.d.ts.map +1 -0
  113. package/lib/client/surface/components/LifecycleDialogs.js +31 -0
  114. package/lib/client/surface/components/LifecycleDialogs.js.map +1 -0
  115. package/lib/client/surface/components/NativeDialogs.d.ts +9 -0
  116. package/lib/client/surface/components/NativeDialogs.d.ts.map +1 -0
  117. package/lib/client/surface/components/NativeDialogs.js +14 -0
  118. package/lib/client/surface/components/NativeDialogs.js.map +1 -0
  119. package/lib/client/surface/components/NotificationToasts.d.ts +7 -0
  120. package/lib/client/surface/components/NotificationToasts.d.ts.map +1 -0
  121. package/lib/client/surface/components/NotificationToasts.js +24 -0
  122. package/lib/client/surface/components/NotificationToasts.js.map +1 -0
  123. package/lib/client/surface/components/RegistrationDialog.d.ts +15 -0
  124. package/lib/client/surface/components/RegistrationDialog.d.ts.map +1 -0
  125. package/lib/client/surface/components/RegistrationDialog.js +22 -0
  126. package/lib/client/surface/components/RegistrationDialog.js.map +1 -0
  127. package/lib/client/surface/components/SurfaceContent.d.ts +31 -0
  128. package/lib/client/surface/components/SurfaceContent.d.ts.map +1 -0
  129. package/lib/client/surface/components/SurfaceContent.js +65 -0
  130. package/lib/client/surface/components/SurfaceContent.js.map +1 -0
  131. package/lib/client/surface/components/SurfaceHeader.d.ts +15 -0
  132. package/lib/client/surface/components/SurfaceHeader.d.ts.map +1 -0
  133. package/lib/client/surface/components/SurfaceHeader.js +42 -0
  134. package/lib/client/surface/components/SurfaceHeader.js.map +1 -0
  135. package/lib/client/surface/components/WorkspaceTree.d.ts +32 -0
  136. package/lib/client/surface/components/WorkspaceTree.d.ts.map +1 -0
  137. package/lib/client/surface/components/WorkspaceTree.js +145 -0
  138. package/lib/client/surface/components/WorkspaceTree.js.map +1 -0
  139. package/lib/client/{worktree-surface-dialogs.d.ts → surface/components/dialogs.d.ts} +5 -2
  140. package/lib/client/surface/components/dialogs.d.ts.map +1 -0
  141. package/lib/client/{worktree-surface-dialogs.js → surface/components/dialogs.js} +67 -24
  142. package/lib/client/surface/components/dialogs.js.map +1 -0
  143. package/lib/client/{worktree-surface-rows.d.ts → surface/components/rows.d.ts} +3 -3
  144. package/lib/client/surface/components/rows.d.ts.map +1 -0
  145. package/lib/client/{worktree-surface-rows.js → surface/components/rows.js} +79 -17
  146. package/lib/client/surface/components/rows.js.map +1 -0
  147. package/lib/client/surface/notification-queue.d.ts +11 -0
  148. package/lib/client/surface/notification-queue.d.ts.map +1 -0
  149. package/lib/client/surface/notification-queue.js +19 -0
  150. package/lib/client/surface/notification-queue.js.map +1 -0
  151. package/lib/client/{worktree-surface-selectors.d.ts → surface/selectors.d.ts} +10 -5
  152. package/lib/client/surface/selectors.d.ts.map +1 -0
  153. package/lib/client/{worktree-surface-selectors.js → surface/selectors.js} +23 -6
  154. package/lib/client/surface/selectors.js.map +1 -0
  155. package/lib/client/surface/shared.d.ts +40 -0
  156. package/lib/client/surface/shared.d.ts.map +1 -0
  157. package/lib/client/surface/shared.js +53 -0
  158. package/lib/client/surface/shared.js.map +1 -0
  159. package/lib/client/surface/state/useLifecycleState.d.ts +34 -0
  160. package/lib/client/surface/state/useLifecycleState.d.ts.map +1 -0
  161. package/lib/client/surface/state/useLifecycleState.js +39 -0
  162. package/lib/client/surface/state/useLifecycleState.js.map +1 -0
  163. package/lib/client/surface/state/useRegistrationState.d.ts +34 -0
  164. package/lib/client/surface/state/useRegistrationState.d.ts.map +1 -0
  165. package/lib/client/surface/state/useRegistrationState.js +44 -0
  166. package/lib/client/surface/state/useRegistrationState.js.map +1 -0
  167. package/lib/client/surface/state/useSessionExpansion.d.ts +39 -0
  168. package/lib/client/surface/state/useSessionExpansion.d.ts.map +1 -0
  169. package/lib/client/surface/state/useSessionExpansion.js +230 -0
  170. package/lib/client/surface/state/useSessionExpansion.js.map +1 -0
  171. package/lib/client/surface/state/useSessionOrdering.d.ts +15 -0
  172. package/lib/client/surface/state/useSessionOrdering.d.ts.map +1 -0
  173. package/lib/client/surface/state/useSessionOrdering.js +68 -0
  174. package/lib/client/surface/state/useSessionOrdering.js.map +1 -0
  175. package/lib/client/surface/state/useSurfaceMenus.d.ts +9 -0
  176. package/lib/client/surface/state/useSurfaceMenus.d.ts.map +1 -0
  177. package/lib/client/surface/state/useSurfaceMenus.js +15 -0
  178. package/lib/client/surface/state/useSurfaceMenus.js.map +1 -0
  179. package/lib/client/surface/state/useSurfaceRefresh.d.ts +39 -0
  180. package/lib/client/surface/state/useSurfaceRefresh.d.ts.map +1 -0
  181. package/lib/client/surface/state/useSurfaceRefresh.js +274 -0
  182. package/lib/client/surface/state/useSurfaceRefresh.js.map +1 -0
  183. package/lib/client/surface/state/useSurfaceSources.d.ts +31 -0
  184. package/lib/client/surface/state/useSurfaceSources.d.ts.map +1 -0
  185. package/lib/client/surface/state/useSurfaceSources.js +63 -0
  186. package/lib/client/surface/state/useSurfaceSources.js.map +1 -0
  187. package/lib/client/{worktree-surface-types.d.ts → surface/types.d.ts} +50 -13
  188. package/lib/client/surface/types.d.ts.map +1 -0
  189. package/lib/client/surface/types.js +2 -0
  190. package/lib/client/surface/types.js.map +1 -0
  191. package/lib/client/{WorktreeModeAction.d.ts → view/WorktreeModeAction.d.ts} +1 -1
  192. package/lib/client/view/WorktreeModeAction.d.ts.map +1 -0
  193. package/lib/client/{WorktreeModeAction.js → view/WorktreeModeAction.js} +1 -1
  194. package/lib/client/view/WorktreeModeAction.js.map +1 -0
  195. package/lib/client/view/navigation.d.ts.map +1 -0
  196. package/lib/client/view/navigation.js.map +1 -0
  197. package/lib/client/view/view-mode-store.d.ts.map +1 -0
  198. package/lib/client/view/view-mode-store.js.map +1 -0
  199. package/lib/client/view/view-mode.d.ts.map +1 -0
  200. package/lib/client/view/view-mode.js.map +1 -0
  201. package/lib/client/{worktree-error-copy.d.ts → view/worktree-error-copy.d.ts} +2 -2
  202. package/lib/client/view/worktree-error-copy.d.ts.map +1 -0
  203. package/lib/client/view/worktree-error-copy.js.map +1 -0
  204. package/lib/client/{worktree-expand-state.d.ts → view/worktree-expand-state.d.ts} +1 -0
  205. package/lib/client/view/worktree-expand-state.d.ts.map +1 -0
  206. package/lib/client/{worktree-expand-state.js → view/worktree-expand-state.js} +11 -0
  207. package/lib/client/view/worktree-expand-state.js.map +1 -0
  208. package/lib/client/{worktree-view-actions.d.ts → view/worktree-view-actions.d.ts} +11 -5
  209. package/lib/client/view/worktree-view-actions.d.ts.map +1 -0
  210. package/lib/client/{worktree-view-actions.js → view/worktree-view-actions.js} +13 -11
  211. package/lib/client/view/worktree-view-actions.js.map +1 -0
  212. package/lib/client/view/worktree-view-errors.d.ts.map +1 -0
  213. package/lib/client/view/worktree-view-errors.js.map +1 -0
  214. package/lib/client/{worktree-view-read.d.ts → view/worktree-view-read.d.ts} +4 -2
  215. package/lib/client/view/worktree-view-read.d.ts.map +1 -0
  216. package/lib/client/{worktree-view-read.js → view/worktree-view-read.js} +4 -1
  217. package/lib/client/view/worktree-view-read.js.map +1 -0
  218. package/lib/client/view/worktree-view.d.ts.map +1 -0
  219. package/lib/client/view/worktree-view.js.map +1 -0
  220. package/lib/client/worktree-connection.d.ts +5 -0
  221. package/lib/client/worktree-connection.d.ts.map +1 -1
  222. package/lib/client/worktree-connection.js +16 -0
  223. package/lib/client/worktree-connection.js.map +1 -1
  224. package/lib/client.js +4295 -2634
  225. package/lib/client.js.map +1 -1
  226. package/lib/contract/index.contract.js +10 -0
  227. package/lib/contract/index.contract.js.map +1 -1
  228. package/lib/contract/index.d.ts +46 -3
  229. package/lib/contract/index.d.ts.map +1 -1
  230. package/lib/contract/index.js +7 -0
  231. package/lib/contract/index.js.map +1 -1
  232. package/lib/host/dsh-read-adapter.d.ts +10 -1
  233. package/lib/host/dsh-read-adapter.d.ts.map +1 -1
  234. package/lib/host/dsh-read-adapter.js +18 -1
  235. package/lib/host/dsh-read-adapter.js.map +1 -1
  236. package/lib/host/remote.d.ts.map +1 -1
  237. package/lib/host/remote.js +14 -0
  238. package/lib/host/remote.js.map +1 -1
  239. package/lib/host/service.d.ts +24 -0
  240. package/lib/host/service.d.ts.map +1 -1
  241. package/lib/host/service.js +39 -1
  242. package/lib/host/service.js.map +1 -1
  243. package/lib/host/worktree-activity.d.ts +13 -0
  244. package/lib/host/worktree-activity.d.ts.map +1 -0
  245. package/lib/host/worktree-activity.js +23 -0
  246. package/lib/host/worktree-activity.js.map +1 -0
  247. package/lib/host/worktree-permission-manager.js +2 -2
  248. package/lib/host/worktree-permission-manager.js.map +1 -1
  249. package/lib/index.d.ts +3 -3
  250. package/lib/index.d.ts.map +1 -1
  251. package/lib/index.js +2 -2
  252. package/lib/index.js.map +1 -1
  253. package/lib/manage/manager-context.d.ts +2 -1
  254. package/lib/manage/manager-context.d.ts.map +1 -1
  255. package/lib/manage/manager-sessions.js +4 -4
  256. package/lib/manage/manager-sessions.js.map +1 -1
  257. package/lib/manage/manager-worktree-lifecycle.d.ts +23 -0
  258. package/lib/manage/manager-worktree-lifecycle.d.ts.map +1 -0
  259. package/lib/manage/manager-worktree-lifecycle.js +165 -0
  260. package/lib/manage/manager-worktree-lifecycle.js.map +1 -0
  261. package/lib/manage/manager-worktrees.d.ts +1 -6
  262. package/lib/manage/manager-worktrees.d.ts.map +1 -1
  263. package/lib/manage/manager-worktrees.js +78 -112
  264. package/lib/manage/manager-worktrees.js.map +1 -1
  265. package/lib/manage/manager.d.ts +17 -1
  266. package/lib/manage/manager.d.ts.map +1 -1
  267. package/lib/manage/manager.js +23 -6
  268. package/lib/manage/manager.js.map +1 -1
  269. package/lib/provider/generated-name.d.ts +8 -0
  270. package/lib/provider/generated-name.d.ts.map +1 -0
  271. package/lib/provider/generated-name.js +29 -0
  272. package/lib/provider/generated-name.js.map +1 -0
  273. package/lib/provider/{git.d.ts → git/adapter.d.ts} +2 -2
  274. package/lib/provider/git/adapter.d.ts.map +1 -0
  275. package/lib/provider/{git.js → git/adapter.js} +11 -2
  276. package/lib/provider/git/adapter.js.map +1 -0
  277. package/lib/provider/{repository-fingerprint.d.ts → git/repository-fingerprint.d.ts} +1 -1
  278. package/lib/provider/git/repository-fingerprint.d.ts.map +1 -0
  279. package/lib/provider/git/repository-fingerprint.js.map +1 -0
  280. package/lib/provider/{subprocess.d.ts → git/subprocess.d.ts} +1 -1
  281. package/lib/provider/git/subprocess.d.ts.map +1 -0
  282. package/lib/provider/git/subprocess.js.map +1 -0
  283. package/lib/provider/git/worktree-status.d.ts +5 -0
  284. package/lib/provider/git/worktree-status.d.ts.map +1 -0
  285. package/lib/provider/git/worktree-status.js +23 -0
  286. package/lib/provider/git/worktree-status.js.map +1 -0
  287. package/lib/provider/index.d.ts +5 -5
  288. package/lib/provider/index.d.ts.map +1 -1
  289. package/lib/provider/index.js +5 -5
  290. package/lib/provider/index.js.map +1 -1
  291. package/lib/provider/mutation-token.d.ts +1 -1
  292. package/lib/provider/mutation-token.d.ts.map +1 -1
  293. package/lib/provider/mutation-token.js +1 -0
  294. package/lib/provider/mutation-token.js.map +1 -1
  295. package/lib/provider/sidecar/mutation-lock.d.ts.map +1 -0
  296. package/lib/provider/{mutation-lock.js → sidecar/mutation-lock.js} +1 -1
  297. package/lib/provider/sidecar/mutation-lock.js.map +1 -0
  298. package/lib/provider/{sidecar.d.ts → sidecar/repository.d.ts} +3 -3
  299. package/lib/provider/sidecar/repository.d.ts.map +1 -0
  300. package/lib/provider/{sidecar.js → sidecar/repository.js} +12 -5
  301. package/lib/provider/sidecar/repository.js.map +1 -0
  302. package/lib/provider/{sidecar-persistence.d.ts → sidecar/sidecar-persistence.d.ts} +1 -1
  303. package/lib/provider/sidecar/sidecar-persistence.d.ts.map +1 -0
  304. package/lib/provider/{sidecar-persistence.js → sidecar/sidecar-persistence.js} +29 -2
  305. package/lib/provider/sidecar/sidecar-persistence.js.map +1 -0
  306. package/lib/provider/{sidecar-schema.d.ts → sidecar/sidecar-schema.d.ts} +1 -1
  307. package/lib/provider/sidecar/sidecar-schema.d.ts.map +1 -0
  308. package/lib/provider/{sidecar-schema.js → sidecar/sidecar-schema.js} +52 -16
  309. package/lib/provider/sidecar/sidecar-schema.js.map +1 -0
  310. package/lib/provider/transaction/dependencies.d.ts +10 -0
  311. package/lib/provider/transaction/dependencies.d.ts.map +1 -0
  312. package/lib/provider/transaction/dependencies.js +2 -0
  313. package/lib/provider/transaction/dependencies.js.map +1 -0
  314. package/lib/provider/transaction/index.d.ts +17 -0
  315. package/lib/provider/transaction/index.d.ts.map +1 -0
  316. package/lib/provider/transaction/index.js +44 -0
  317. package/lib/provider/transaction/index.js.map +1 -0
  318. package/lib/provider/transaction/operations/adopt-branch.d.ts +6 -0
  319. package/lib/provider/transaction/operations/adopt-branch.d.ts.map +1 -0
  320. package/lib/provider/transaction/operations/adopt-branch.js +59 -0
  321. package/lib/provider/transaction/operations/adopt-branch.js.map +1 -0
  322. package/lib/provider/transaction/operations/clean.d.ts +4 -0
  323. package/lib/provider/transaction/operations/clean.d.ts.map +1 -0
  324. package/lib/provider/transaction/operations/clean.js +168 -0
  325. package/lib/provider/transaction/operations/clean.js.map +1 -0
  326. package/lib/provider/transaction/operations/create.d.ts +5 -0
  327. package/lib/provider/transaction/operations/create.d.ts.map +1 -0
  328. package/lib/provider/transaction/operations/create.js +136 -0
  329. package/lib/provider/transaction/operations/create.js.map +1 -0
  330. package/lib/provider/transaction/operations/import.d.ts +5 -0
  331. package/lib/provider/transaction/operations/import.d.ts.map +1 -0
  332. package/lib/provider/transaction/operations/import.js +92 -0
  333. package/lib/provider/transaction/operations/import.js.map +1 -0
  334. package/lib/provider/transaction/operations/remove.d.ts +4 -0
  335. package/lib/provider/transaction/operations/remove.d.ts.map +1 -0
  336. package/lib/provider/transaction/operations/remove.js +164 -0
  337. package/lib/provider/transaction/operations/remove.js.map +1 -0
  338. package/lib/provider/transaction/recovery/failure-recovery.d.ts +32 -0
  339. package/lib/provider/transaction/recovery/failure-recovery.d.ts.map +1 -0
  340. package/lib/provider/transaction/recovery/failure-recovery.js +147 -0
  341. package/lib/provider/transaction/recovery/failure-recovery.js.map +1 -0
  342. package/lib/provider/transaction/recovery/recover.d.ts +4 -0
  343. package/lib/provider/transaction/recovery/recover.d.ts.map +1 -0
  344. package/lib/provider/transaction/recovery/recover.js +162 -0
  345. package/lib/provider/transaction/recovery/recover.js.map +1 -0
  346. package/lib/provider/transaction/support/admission.d.ts +7 -0
  347. package/lib/provider/transaction/support/admission.d.ts.map +1 -0
  348. package/lib/provider/transaction/support/admission.js +90 -0
  349. package/lib/provider/transaction/support/admission.js.map +1 -0
  350. package/lib/provider/transaction/support/inspection.d.ts +11 -0
  351. package/lib/provider/transaction/support/inspection.d.ts.map +1 -0
  352. package/lib/provider/transaction/support/inspection.js +51 -0
  353. package/lib/provider/transaction/support/inspection.js.map +1 -0
  354. package/lib/provider/transaction/support/journal.d.ts +12 -0
  355. package/lib/provider/transaction/support/journal.d.ts.map +1 -0
  356. package/lib/provider/transaction/support/journal.js +72 -0
  357. package/lib/provider/transaction/support/journal.js.map +1 -0
  358. package/lib/provider/transaction/support/locking.d.ts +4 -0
  359. package/lib/provider/transaction/support/locking.d.ts.map +1 -0
  360. package/lib/provider/transaction/support/locking.js +11 -0
  361. package/lib/provider/transaction/support/locking.js.map +1 -0
  362. package/lib/provider/transaction/support/path-safety.d.ts +11 -0
  363. package/lib/provider/transaction/support/path-safety.d.ts.map +1 -0
  364. package/lib/provider/transaction/support/path-safety.js +82 -0
  365. package/lib/provider/transaction/support/path-safety.js.map +1 -0
  366. package/lib/provider/transaction/support/paths.d.ts +10 -0
  367. package/lib/provider/transaction/support/paths.d.ts.map +1 -0
  368. package/lib/provider/transaction/support/paths.js +68 -0
  369. package/lib/provider/transaction/support/paths.js.map +1 -0
  370. package/lib/provider/transaction/support/publication.d.ts +9 -0
  371. package/lib/provider/transaction/support/publication.d.ts.map +1 -0
  372. package/lib/provider/transaction/support/publication.js +92 -0
  373. package/lib/provider/transaction/support/publication.js.map +1 -0
  374. package/lib/provider/transaction/types.d.ts +38 -0
  375. package/lib/provider/transaction/types.d.ts.map +1 -0
  376. package/lib/provider/transaction/types.js +2 -0
  377. package/lib/provider/transaction/types.js.map +1 -0
  378. package/lib/provider/types.d.ts +22 -3
  379. package/lib/provider/types.d.ts.map +1 -1
  380. package/lib/provider/types.js +1 -1
  381. package/lib/provider/types.js.map +1 -1
  382. package/lib/provider/worktree-lifecycle.d.ts +19 -0
  383. package/lib/provider/worktree-lifecycle.d.ts.map +1 -0
  384. package/lib/provider/worktree-lifecycle.js +44 -0
  385. package/lib/provider/worktree-lifecycle.js.map +1 -0
  386. package/lib/typert.host.js +269 -30
  387. package/lib/typert.remote-client.d.ts +10 -0
  388. package/lib/typert.remote-client.d.ts.map +1 -1
  389. package/lib/typert.remote-client.js +269 -30
  390. package/package.json +1 -1
  391. package/lib/client/WorktreeContext.d.ts.map +0 -1
  392. package/lib/client/WorktreeContext.js.map +0 -1
  393. package/lib/client/WorktreeHeroContext.d.ts.map +0 -1
  394. package/lib/client/WorktreeHeroContext.js.map +0 -1
  395. package/lib/client/WorktreeModeAction.d.ts.map +0 -1
  396. package/lib/client/WorktreeModeAction.js.map +0 -1
  397. package/lib/client/WorktreeOverlay.d.ts.map +0 -1
  398. package/lib/client/WorktreeOverlay.js.map +0 -1
  399. package/lib/client/dsh-rc1-slot-contract.d.ts +0 -43
  400. package/lib/client/dsh-rc1-slot-contract.d.ts.map +0 -1
  401. package/lib/client/dsh-rc1-slot-contract.js +0 -2
  402. package/lib/client/dsh-rc1-slot-contract.js.map +0 -1
  403. package/lib/client/navigation.d.ts.map +0 -1
  404. package/lib/client/navigation.js.map +0 -1
  405. package/lib/client/overlay-bounds.d.ts.map +0 -1
  406. package/lib/client/overlay-bounds.js.map +0 -1
  407. package/lib/client/session-view.d.ts.map +0 -1
  408. package/lib/client/session-view.js.map +0 -1
  409. package/lib/client/sidebar-overlay-geometry.d.ts.map +0 -1
  410. package/lib/client/sidebar-overlay-geometry.js.map +0 -1
  411. package/lib/client/view-mode-store.d.ts.map +0 -1
  412. package/lib/client/view-mode-store.js.map +0 -1
  413. package/lib/client/view-mode.d.ts.map +0 -1
  414. package/lib/client/view-mode.js.map +0 -1
  415. package/lib/client/virtual-workspace-membership.d.ts.map +0 -1
  416. package/lib/client/virtual-workspace-membership.js.map +0 -1
  417. package/lib/client/worktree-context-store.d.ts.map +0 -1
  418. package/lib/client/worktree-context-store.js.map +0 -1
  419. package/lib/client/worktree-context.d.ts.map +0 -1
  420. package/lib/client/worktree-context.js.map +0 -1
  421. package/lib/client/worktree-error-copy.d.ts.map +0 -1
  422. package/lib/client/worktree-error-copy.js.map +0 -1
  423. package/lib/client/worktree-expand-state.d.ts.map +0 -1
  424. package/lib/client/worktree-expand-state.js.map +0 -1
  425. package/lib/client/worktree-permission-icon.d.ts.map +0 -1
  426. package/lib/client/worktree-permission-icon.js.map +0 -1
  427. package/lib/client/worktree-permission.d.ts.map +0 -1
  428. package/lib/client/worktree-permission.js.map +0 -1
  429. package/lib/client/worktree-session-fork.d.ts.map +0 -1
  430. package/lib/client/worktree-session-fork.js.map +0 -1
  431. package/lib/client/worktree-session-order.d.ts.map +0 -1
  432. package/lib/client/worktree-session-order.js.map +0 -1
  433. package/lib/client/worktree-session-position.d.ts.map +0 -1
  434. package/lib/client/worktree-session-position.js.map +0 -1
  435. package/lib/client/worktree-session.d.ts.map +0 -1
  436. package/lib/client/worktree-session.js.map +0 -1
  437. package/lib/client/worktree-surface-dialogs.d.ts.map +0 -1
  438. package/lib/client/worktree-surface-dialogs.js.map +0 -1
  439. package/lib/client/worktree-surface-rows.d.ts.map +0 -1
  440. package/lib/client/worktree-surface-rows.js.map +0 -1
  441. package/lib/client/worktree-surface-selectors.d.ts.map +0 -1
  442. package/lib/client/worktree-surface-selectors.js.map +0 -1
  443. package/lib/client/worktree-surface-types.d.ts.map +0 -1
  444. package/lib/client/worktree-surface-types.js +0 -2
  445. package/lib/client/worktree-surface-types.js.map +0 -1
  446. package/lib/client/worktree-view-actions.d.ts.map +0 -1
  447. package/lib/client/worktree-view-actions.js.map +0 -1
  448. package/lib/client/worktree-view-errors.d.ts.map +0 -1
  449. package/lib/client/worktree-view-errors.js.map +0 -1
  450. package/lib/client/worktree-view-read.d.ts.map +0 -1
  451. package/lib/client/worktree-view-read.js.map +0 -1
  452. package/lib/client/worktree-view.d.ts.map +0 -1
  453. package/lib/client/worktree-view.js.map +0 -1
  454. package/lib/provider/git.d.ts.map +0 -1
  455. package/lib/provider/git.js.map +0 -1
  456. package/lib/provider/mutation-lock.d.ts.map +0 -1
  457. package/lib/provider/mutation-lock.js.map +0 -1
  458. package/lib/provider/repository-fingerprint.d.ts.map +0 -1
  459. package/lib/provider/repository-fingerprint.js.map +0 -1
  460. package/lib/provider/sidecar-persistence.d.ts.map +0 -1
  461. package/lib/provider/sidecar-persistence.js.map +0 -1
  462. package/lib/provider/sidecar-schema.d.ts.map +0 -1
  463. package/lib/provider/sidecar-schema.js.map +0 -1
  464. package/lib/provider/sidecar.d.ts.map +0 -1
  465. package/lib/provider/sidecar.js.map +0 -1
  466. package/lib/provider/subprocess.d.ts.map +0 -1
  467. package/lib/provider/subprocess.js.map +0 -1
  468. package/lib/provider/transaction.d.ts +0 -65
  469. package/lib/provider/transaction.d.ts.map +0 -1
  470. package/lib/provider/transaction.js +0 -1011
  471. package/lib/provider/transaction.js.map +0 -1
  472. /package/lib/client/{WorktreeContext.js → context/WorktreeContext.js} +0 -0
  473. /package/lib/client/{WorktreeHeroContext.js → context/WorktreeHeroContext.js} +0 -0
  474. /package/lib/client/{overlay-bounds.d.ts → overlay/overlay-bounds.d.ts} +0 -0
  475. /package/lib/client/{overlay-bounds.js → overlay/overlay-bounds.js} +0 -0
  476. /package/lib/client/{sidebar-overlay-geometry.d.ts → overlay/sidebar-overlay-geometry.d.ts} +0 -0
  477. /package/lib/client/{sidebar-overlay-geometry.js → overlay/sidebar-overlay-geometry.js} +0 -0
  478. /package/lib/client/{worktree-permission-icon.d.ts → permission/worktree-permission-icon.d.ts} +0 -0
  479. /package/lib/client/{worktree-permission-icon.js → permission/worktree-permission-icon.js} +0 -0
  480. /package/lib/client/{worktree-permission.d.ts → permission/worktree-permission.d.ts} +0 -0
  481. /package/lib/client/{worktree-permission.js → permission/worktree-permission.js} +0 -0
  482. /package/lib/client/{session-view.d.ts → session/session-view.d.ts} +0 -0
  483. /package/lib/client/{session-view.js → session/session-view.js} +0 -0
  484. /package/lib/client/{worktree-session-order.d.ts → session/worktree-session-order.d.ts} +0 -0
  485. /package/lib/client/{worktree-session-order.js → session/worktree-session-order.js} +0 -0
  486. /package/lib/client/{worktree-session-position.d.ts → session/worktree-session-position.d.ts} +0 -0
  487. /package/lib/client/{worktree-session-position.js → session/worktree-session-position.js} +0 -0
  488. /package/lib/client/{navigation.d.ts → view/navigation.d.ts} +0 -0
  489. /package/lib/client/{navigation.js → view/navigation.js} +0 -0
  490. /package/lib/client/{view-mode-store.d.ts → view/view-mode-store.d.ts} +0 -0
  491. /package/lib/client/{view-mode-store.js → view/view-mode-store.js} +0 -0
  492. /package/lib/client/{view-mode.d.ts → view/view-mode.d.ts} +0 -0
  493. /package/lib/client/{view-mode.js → view/view-mode.js} +0 -0
  494. /package/lib/client/{worktree-error-copy.js → view/worktree-error-copy.js} +0 -0
  495. /package/lib/client/{worktree-view-errors.d.ts → view/worktree-view-errors.d.ts} +0 -0
  496. /package/lib/client/{worktree-view-errors.js → view/worktree-view-errors.js} +0 -0
  497. /package/lib/client/{worktree-view.d.ts → view/worktree-view.d.ts} +0 -0
  498. /package/lib/client/{worktree-view.js → view/worktree-view.js} +0 -0
  499. /package/lib/provider/{repository-fingerprint.js → git/repository-fingerprint.js} +0 -0
  500. /package/lib/provider/{subprocess.js → git/subprocess.js} +0 -0
  501. /package/lib/provider/{mutation-lock.d.ts → sidecar/mutation-lock.d.ts} +0 -0
@@ -1,1430 +1,55 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
3
- import { IconBranchOutline16, IconCloseOutline16, IconProjectAddOutline16, IconSearchOutline16, RiskConfirmation, } from '@deepseek-ai/dsh-client-ui-primitives';
4
- import { openWorktreeSession } from './navigation.js';
5
- import { useSidebarOverlayGeometry } from './sidebar-overlay-geometry.js';
6
- import { isMainExpanded, isWorkspaceExpanded, isWorktreeExpanded, } from './worktree-expand-state.js';
7
- import { effectiveViewMode, unboundSessionIds, workspaceSessionIds } from './view-mode.js';
8
- import { formatWorktreePermissionNotice, formatWorktreeViewError, } from './worktree-error-copy.js';
9
- import { deriveSessionPresentationIndex, filterVisibleSessionIds, hasOngoingSession, sessionMatchesQuery, } from './session-view.js';
10
- import { nextSessionOrderAccount, reorderSessionIds, } from './worktree-session-order.js';
11
- import { retryWorktreeSessionBinding } from './worktree-session.js';
12
- import { WorktreeCreateDialog, WorktreeRemovalDialog, WorktreeSessionRenameDialog, WorktreeWorkspaceDeleteDialog, WorktreeWorkspaceRenameDialog, } from './worktree-surface-dialogs.js';
13
- import { bindingIdsFor, clearSessionGroupExpansion, includesText, isCompleteWorktreeWorkspaceSnapshot, currentSessionRevealKeys, isSessionGroupAutoExpanded, resolveCurrentSessionLocation, workspaceMatches, } from './worktree-surface-selectors.js';
14
- import { scrollCurrentSessionIntoView } from './worktree-session-position.js';
15
- import { WorktreeGroupRow, WorktreeSessionGroup, WorktreeWorkspaceRow, } from './worktree-surface-rows.js';
16
- import { executeWorktreeAction, createDefaultWorktreeName, createNumberedWorktreeName, createWorktreeModalViewLoader, createWorktreeRefreshGuard, filterArchivedSessionIds, mergeWorktreeView, mergeWorktreeViews, reconcileBaseBranchSelection, resolveWorktreeMove, selectDefaultBaseBranch, stableWorkspaceIds, toRetryableWorktreeOrderError, toWorktreeViewError, WorktreeSessionBindingError, WorktreeSessionPermissionError, } from './worktree-view.js';
2
+ import { AccessConfirmation } from './surface/components/AccessConfirmation.js';
3
+ import { LifecycleDialogs } from './surface/components/LifecycleDialogs.js';
4
+ import { NativeDialogs } from './surface/components/NativeDialogs.js';
5
+ import { RegistrationDialog } from './surface/components/RegistrationDialog.js';
6
+ import { SurfaceContent } from './surface/components/SurfaceContent.js';
7
+ import { SurfaceHeader } from './surface/components/SurfaceHeader.js';
8
+ import { useDragActions } from './surface/actions/useDragActions.js';
9
+ import { useLifecycleActions } from './surface/actions/useLifecycleActions.js';
10
+ import { useLifecycleState } from './surface/state/useLifecycleState.js';
11
+ import { useNativeActions } from './surface/actions/useNativeActions.js';
12
+ import { useRegistrationState } from './surface/state/useRegistrationState.js';
13
+ import { useSessionActions } from './surface/actions/useSessionActions.js';
14
+ import { useSessionExpansion } from './surface/state/useSessionExpansion.js';
15
+ import { useSessionOrdering } from './surface/state/useSessionOrdering.js';
16
+ import { useSurfaceMenus } from './surface/state/useSurfaceMenus.js';
17
+ import { useSurfaceMutation } from './surface/actions/useSurfaceMutation.js';
18
+ import { useSurfaceRefresh } from './surface/state/useSurfaceRefresh.js';
19
+ import { useSurfaceSources } from './surface/state/useSurfaceSources.js';
20
+ import { useWorktreeRegistration } from './surface/actions/useWorktreeRegistration.js';
17
21
  import styles from './worktree.css';
18
- function toNativeWorktreeViewError(error) {
19
- const viewError = toWorktreeViewError(error);
20
- if (typeof error === 'object' && error !== null)
21
- return viewError;
22
- return { ...viewError, message: String(error) };
23
- }
24
- const EMPTY_READ_STATE = { status: 'idle', views: [] };
25
- const EMPTY_PERMISSION_NOTICE = undefined;
26
- const EMPTY_PERMISSION_NOTICE_SUBSCRIBE = () => () => { };
27
- const EMPTY_PERMISSION_NOTICE_SNAPSHOT = () => EMPTY_PERMISSION_NOTICE;
28
- const EMPTY_FULL_ACCESS_CONFIRMATION_SUBSCRIBE = () => () => { };
29
- const EMPTY_FULL_ACCESS_CONFIRMATION_SNAPSHOT = () => undefined;
30
- const EMPTY_FORK_RECOVERY_SNAPSHOT = {
31
- revision: 0,
32
- pending: [],
33
- affectedWorkspaceIds: [],
34
- };
35
- const EMPTY_FORK_RECOVERY_STORE = {
36
- getSnapshot: () => EMPTY_FORK_RECOVERY_SNAPSHOT,
37
- subscribe: () => () => { },
38
- };
39
- function updatedAtById(sessionIds, sessions) {
40
- return Object.fromEntries(sessionIds.map((sessionId) => [sessionId, sessions.byId[sessionId]?.updatedAt]));
41
- }
42
- function forkRecoveryError(recovery) {
43
- const error = toNativeWorktreeViewError(recovery.error);
44
- return {
45
- ...error,
46
- code: error.code === 'WORKTREE_VIEW_FAILED' ? 'SESSION_BINDING_FAILED' : error.code,
47
- details: {
48
- ...(error.details ?? {}),
49
- sessionId: recovery.childSessionId,
50
- },
51
- };
52
- }
53
- function useStableWorkspaceIds(workspaces) {
54
- const next = workspaces.map((workspace) => workspace.workspaceId);
55
- const previousRef = useRef([]);
56
- const stable = stableWorkspaceIds(previousRef.current, next);
57
- if (stable !== previousRef.current)
58
- previousRef.current = stable;
59
- return previousRef.current;
60
- }
61
- /**
62
- * Peer Worktree navigation surface. It keeps the original DSH Workspace mode
63
- * intact and renders a browser-local Workspace → Worktree → Session projection.
64
- */
65
- export function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, expandState, sessionOrder, manager, viewReader, permission, confirmFullAccess, fullAccessConfirmation, onPermissionResult, onPermissionNotice, permissionNotice, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, forkRecovery, retryForkSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }) {
66
- const preferredMode = useStore((state) => state.viewMode);
67
- const mode = effectiveViewMode(preferredMode, available && manager !== undefined);
68
- const sessions = useSessions((state) => state);
69
- const workspaces = useWorkspaces((state) => state);
70
- const forkRecoveryStore = forkRecovery ?? EMPTY_FORK_RECOVERY_STORE;
71
- const forkRecoverySnapshot = useSyncExternalStore(forkRecoveryStore.subscribe, forkRecoveryStore.getSnapshot, forkRecoveryStore.getSnapshot);
72
- const currentSessionId = sessions.current;
73
- const workspaceIds = useStableWorkspaceIds(workspaces.items);
74
- const workspaceIdsRef = useRef(workspaceIds);
75
- workspaceIdsRef.current = workspaceIds;
76
- const [readState, setReadState] = useState(EMPTY_READ_STATE);
77
- const expandSnapshot = useSyncExternalStore(expandState.subscribe, expandState.getSnapshot, expandState.getSnapshot);
78
- const permissionNoticeSnapshot = useSyncExternalStore(permissionNotice?.subscribe ?? EMPTY_PERMISSION_NOTICE_SUBSCRIBE, permissionNotice?.getSnapshot ?? EMPTY_PERMISSION_NOTICE_SNAPSHOT, permissionNotice?.getSnapshot ?? EMPTY_PERMISSION_NOTICE_SNAPSHOT);
79
- const fullAccessConfirmationSnapshot = useSyncExternalStore(fullAccessConfirmation?.subscribe ?? EMPTY_FULL_ACCESS_CONFIRMATION_SUBSCRIBE, fullAccessConfirmation?.getSnapshot ?? EMPTY_FULL_ACCESS_CONFIRMATION_SNAPSHOT, fullAccessConfirmation?.getSnapshot ?? EMPTY_FULL_ACCESS_CONFIRMATION_SNAPSHOT);
80
- const fullAccessConfirmationKey = fullAccessConfirmationSnapshot === undefined
81
- ? ''
82
- : [
83
- fullAccessConfirmationSnapshot.workspaceId,
84
- fullAccessConfirmationSnapshot.worktreeId,
85
- fullAccessConfirmationSnapshot.sessionId,
86
- fullAccessConfirmationSnapshot.cwd,
87
- ].join('\u0000');
88
- const [fullAccessAcknowledged, setFullAccessAcknowledged] = useState(false);
89
- useEffect(() => {
90
- setFullAccessAcknowledged(false);
91
- }, [fullAccessConfirmationKey]);
92
- const sessionOrderSnapshot = useSyncExternalStore(sessionOrder.subscribe, sessionOrder.getSnapshot, sessionOrder.getSnapshot);
93
- const sessionPresentations = useMemo(() => deriveSessionPresentationIndex(sessions), [sessions.byId]);
94
- const readStateRef = useRef(readState);
95
- readStateRef.current = readState;
96
- const [searchQuery, setSearchQuery] = useState('');
97
- const [currentSessionReveal, setCurrentSessionReveal] = useState();
98
- const searchQueryRef = useRef(searchQuery);
99
- searchQueryRef.current = searchQuery;
100
- const locateGenerationRef = useRef(0);
101
- const positionedLocateGenerationRef = useRef();
102
- const [worktreeModalWorkspaceId, setWorktreeModalWorkspaceId] = useState();
103
- const [modalReadError, setModalReadError] = useState();
104
- const [modalReadLoading, setModalReadLoading] = useState(false);
105
- const [worktreeModalMode, setWorktreeModalMode] = useState('create');
106
- const [importCandidates, setImportCandidates] = useState({
107
- status: 'idle',
108
- candidates: [],
22
+ /** Composes independent surface state/action domains into the sidebar overlay. */
23
+ export function WorktreeSurface(props) {
24
+ const source = useSurfaceSources({ props });
25
+ const registrationState = useRegistrationState({ props });
26
+ const read = useSurfaceRefresh({ source, props, registrationState });
27
+ const mutation = useSurfaceMutation({ read });
28
+ const lifecycleState = useLifecycleState({ props, source, mutation });
29
+ const menus = useSurfaceMenus();
30
+ const ordering = useSessionOrdering({ read, source, props });
31
+ const expansion = useSessionExpansion({ read, source, props });
32
+ const native = useNativeActions({ source, props, mutation });
33
+ const drag = useDragActions({ source, props, mutation, read });
34
+ const session = useSessionActions({ source, props, mutation, read });
35
+ const registration = useWorktreeRegistration({
36
+ source,
37
+ registrationState,
38
+ read,
39
+ props,
40
+ mutation,
41
+ session,
109
42
  });
110
- const [selectedImportPath, setSelectedImportPath] = useState();
111
- const [openWorkspaceMenuId, setOpenWorkspaceMenuId] = useState();
112
- const [openMainMenuId, setOpenMainMenuId] = useState();
113
- const [openWorktreeMenuId, setOpenWorktreeMenuId] = useState();
114
- const [worktreeRemoval, setWorktreeRemoval] = useState();
115
- const [selectedBranch, setSelectedBranch] = useState('');
116
- const [newBranch, setNewBranch] = useState('');
117
- const [pendingSessionBinding, setPendingSessionBinding] = useState();
118
- const [actionError, setActionError] = useState();
119
- const [actionPending, setActionPending] = useState(false);
120
- const [forkRetryKey, setForkRetryKey] = useState();
121
- const [sessionRenameTarget, setSessionRenameTarget] = useState();
122
- const [sessionRenameDraft, setSessionRenameDraft] = useState('');
123
- const [sessionRenamePending, setSessionRenamePending] = useState(false);
124
- const [sessionRenameError, setSessionRenameError] = useState();
125
- const [workspaceDrag, setWorkspaceDrag] = useState();
126
- const [workspaceRenameTarget, setWorkspaceRenameTarget] = useState();
127
- const [workspaceRenameDraft, setWorkspaceRenameDraft] = useState('');
128
- const [workspaceRenamePending, setWorkspaceRenamePending] = useState(false);
129
- const [workspaceRenameError, setWorkspaceRenameError] = useState();
130
- const [workspaceDeleteTarget, setWorkspaceDeleteTarget] = useState();
131
- const [workspaceDeletePending, setWorkspaceDeletePending] = useState(false);
132
- const [workspaceDeleteError, setWorkspaceDeleteError] = useState();
133
- const workspaceDropCommitted = useRef(false);
134
- const [sessionDrag, setSessionDrag] = useState();
135
- const [expandedSessionGroups, setExpandedSessionGroups] = useState({});
136
- const sessionDropCommitted = useRef(false);
137
- const [worktreeDrag, setWorktreeDrag] = useState();
138
- const worktreeDropCommitted = useRef(false);
139
- const refreshGuard = useRef(createWorktreeRefreshGuard());
140
- const targetRefreshGuards = useRef(new Map());
141
- const forkRecoveryRevisionRef = useRef(forkRecoverySnapshot.revision);
142
- const modalReadLoader = useRef(createWorktreeModalViewLoader(viewReader));
143
- const modalReadViewRef = useRef();
144
- const importCandidatesGuard = useRef(createWorktreeRefreshGuard());
145
- const modalWorkspaceIdRef = useRef(worktreeModalWorkspaceId);
146
- modalWorkspaceIdRef.current = worktreeModalWorkspaceId;
147
- const { ref, width, bounds } = useSidebarOverlayGeometry(mode === 'worktree');
148
- const collapsed = width <= 64;
149
- const query = searchQuery.trim().toLocaleLowerCase();
150
- const archivedSessionIds = workspaces.archivedSessionIds ?? [];
151
- const pendingSessionArchived = pendingSessionBinding !== undefined &&
152
- archivedSessionIds.includes(pendingSessionBinding.sessionId);
153
- const guardFor = (workspaceId) => {
154
- const current = targetRefreshGuards.current.get(workspaceId);
155
- if (current !== undefined)
156
- return current;
157
- const created = createWorktreeRefreshGuard();
158
- targetRefreshGuards.current.set(workspaceId, created);
159
- return created;
160
- };
161
- const refresh = useCallback(async (options = {}) => {
162
- if (manager === undefined) {
163
- refreshGuard.current.invalidate();
164
- for (const guard of targetRefreshGuards.current.values())
165
- guard.invalidate();
166
- setReadState(EMPTY_READ_STATE);
167
- return;
168
- }
169
- const scope = options.scope ?? { kind: 'global' };
170
- const preserveCurrent = options.preserveCurrent === true;
171
- const currentWorkspaceIds = workspaceIdsRef.current;
172
- if (scope.kind === 'global') {
173
- if (!preserveCurrent) {
174
- setReadState({ status: 'loading', views: [] });
175
- }
176
- const selectedWorkspaceIds = [...currentWorkspaceIds];
177
- for (const workspaceId of selectedWorkspaceIds) {
178
- viewReader.invalidate(workspaceId);
179
- }
180
- const contextRefresh = options.invalidateContext === false
181
- ? undefined
182
- : invalidateWorktreeContext?.();
183
- await refreshGuard.current.run(async () => {
184
- const [views] = await Promise.all([
185
- viewReader.readMany(selectedWorkspaceIds),
186
- contextRefresh ?? Promise.resolve(),
187
- ]);
188
- return views;
189
- }, (views) => {
190
- setReadState((current) => {
191
- const merged = mergeWorktreeViews(current.views, workspaceIdsRef.current, views);
192
- return {
193
- status: 'ready',
194
- views: modalReadViewRef.current === undefined
195
- ? merged
196
- : mergeWorktreeView(merged, modalReadViewRef.current),
197
- };
198
- });
199
- }, (error) => {
200
- if (preserveCurrent)
201
- throw error;
202
- setReadState({
203
- status: 'error',
204
- views: modalReadViewRef.current === undefined ? [] : [modalReadViewRef.current],
205
- error: toWorktreeViewError(error),
206
- });
207
- });
208
- return;
209
- }
210
- const requestedWorkspaceIds = scope.kind === 'workspace'
211
- ? [scope.workspaceId]
212
- : scope.workspaceIds;
213
- const selectedWorkspaceIds = [...new Set(requestedWorkspaceIds)].filter((workspaceId) => currentWorkspaceIds.includes(workspaceId));
214
- if (selectedWorkspaceIds.length === 0)
215
- return;
216
- await Promise.allSettled(selectedWorkspaceIds.map(async (workspaceId) => {
217
- const guard = guardFor(workspaceId);
218
- viewReader.invalidate(workspaceId);
219
- const contextRefresh = options.invalidateContext === false
220
- ? undefined
221
- : invalidateWorktreeContext?.(workspaceId);
222
- const generation = guard.begin();
223
- try {
224
- const view = await viewReader.read(workspaceId);
225
- if (!guard.isCurrent(generation))
226
- return;
227
- if (!workspaceIdsRef.current.includes(workspaceId))
228
- return;
229
- setReadState((current) => {
230
- const remainingTargetError = current.targetError?.workspaceIds.filter((candidate) => candidate !== workspaceId) ?? [];
231
- const next = {
232
- ...current,
233
- status: 'ready',
234
- views: mergeWorktreeViews(current.views, workspaceIdsRef.current, [view]),
235
- error: undefined,
236
- };
237
- if (remainingTargetError.length === 0) {
238
- const withoutTargetError = { ...next };
239
- delete withoutTargetError.targetError;
240
- return withoutTargetError;
241
- }
242
- return {
243
- ...next,
244
- targetError: {
245
- workspaceIds: remainingTargetError,
246
- error: current.targetError.error,
247
- },
248
- };
249
- });
250
- }
251
- catch (error) {
252
- if (!guard.isCurrent(generation))
253
- return;
254
- if (!workspaceIdsRef.current.includes(workspaceId))
255
- return;
256
- setReadState((current) => {
257
- const previousIds = current.targetError?.workspaceIds ?? [];
258
- return {
259
- ...current,
260
- status: 'ready',
261
- views: mergeWorktreeViews(current.views, workspaceIdsRef.current, []),
262
- error: undefined,
263
- targetError: {
264
- workspaceIds: [...new Set([...previousIds, workspaceId])],
265
- error: {
266
- ...toWorktreeViewError(error),
267
- retryable: true,
268
- },
269
- },
270
- };
271
- });
272
- }
273
- finally {
274
- await contextRefresh?.catch(() => undefined);
275
- }
276
- }));
277
- }, [invalidateWorktreeContext, manager, viewReader]);
278
- const loadModalWorktreeView = useCallback((workspaceId) => {
279
- setModalReadError(undefined);
280
- setModalReadLoading(true);
281
- if (manager === undefined) {
282
- setModalReadLoading(false);
283
- setModalReadError({
284
- code: 'WORKTREE_VIEW_UNAVAILABLE',
285
- message: '',
286
- retryable: true,
287
- });
288
- return;
289
- }
290
- void modalReadLoader.current.load(workspaceId, (view) => {
291
- modalReadViewRef.current = view;
292
- setModalReadLoading(false);
293
- setReadState((current) => ({
294
- ...current,
295
- views: mergeWorktreeView(current.views, view),
296
- }));
297
- }, (error) => {
298
- setModalReadLoading(false);
299
- setModalReadError(toWorktreeViewError(error));
300
- });
301
- }, [manager, viewReader]);
302
- useEffect(() => {
303
- if (mode === 'worktree') {
304
- void refresh({ preserveCurrent: readStateRef.current.status === 'ready' });
305
- }
306
- else {
307
- refreshGuard.current.invalidate();
308
- for (const guard of targetRefreshGuards.current.values())
309
- guard.invalidate();
310
- modalReadLoader.current.invalidate();
311
- modalReadViewRef.current = undefined;
312
- setWorktreeModalWorkspaceId(undefined);
313
- setModalReadError(undefined);
314
- setModalReadLoading(false);
315
- setReadState(EMPTY_READ_STATE);
316
- }
317
- }, [mode, refresh]);
318
- const previousWorkspaceIdsRef = useRef(workspaceIds);
319
- useEffect(() => {
320
- const previousWorkspaceIds = previousWorkspaceIdsRef.current;
321
- previousWorkspaceIdsRef.current = workspaceIds;
322
- if (mode !== 'worktree')
323
- return;
324
- const addedWorkspaceIds = workspaceIds.filter((workspaceId) => !previousWorkspaceIds.includes(workspaceId));
325
- const removedWorkspaceIds = previousWorkspaceIds.filter((workspaceId) => !workspaceIds.includes(workspaceId));
326
- for (const workspaceId of removedWorkspaceIds) {
327
- targetRefreshGuards.current.delete(workspaceId);
328
- }
329
- setReadState((current) => {
330
- const views = mergeWorktreeViews(current.views, workspaceIds, []);
331
- const remainingTargetError = current.targetError?.workspaceIds.filter((workspaceId) => workspaceIds.includes(workspaceId)) ?? [];
332
- const next = { ...current, views };
333
- if (remainingTargetError.length === 0) {
334
- const withoutTargetError = { ...next };
335
- delete withoutTargetError.targetError;
336
- return withoutTargetError;
337
- }
338
- return {
339
- ...next,
340
- targetError: {
341
- workspaceIds: remainingTargetError,
342
- error: current.targetError.error,
343
- },
344
- };
345
- });
346
- for (const workspaceId of addedWorkspaceIds) {
347
- void refresh({
348
- scope: { kind: 'workspace', workspaceId },
349
- preserveCurrent: true,
350
- }).catch(() => {
351
- // The target error remains visible and can be retried explicitly.
352
- });
353
- }
354
- }, [mode, refresh, workspaceIds]);
355
- useEffect(() => {
356
- if (forkRecoveryRevisionRef.current === forkRecoverySnapshot.revision)
357
- return;
358
- forkRecoveryRevisionRef.current = forkRecoverySnapshot.revision;
359
- if (mode !== 'worktree' || manager === undefined)
360
- return;
361
- if (forkRecoverySnapshot.affectedWorkspaceIds.length === 0)
362
- return;
363
- void refresh({
364
- scope: {
365
- kind: 'workspaces',
366
- workspaceIds: forkRecoverySnapshot.affectedWorkspaceIds,
367
- },
368
- preserveCurrent: readStateRef.current.status === 'ready',
369
- }).catch(() => {
370
- // Recovery state remains visible; the next explicit retry can refresh it again.
371
- });
372
- }, [
373
- forkRecoverySnapshot.affectedWorkspaceIds,
374
- forkRecoverySnapshot.revision,
375
- manager,
376
- mode,
377
- refresh,
378
- ]);
379
- useEffect(() => {
380
- if (readState.status !== 'ready' || syncSessionWorkspaces === undefined)
381
- return;
382
- syncSessionWorkspaces(readState.views.flatMap((view) => view.bindings.map((binding) => ({
383
- workspaceId: binding.workspaceId,
384
- sessionId: binding.sessionId,
385
- }))));
386
- }, [readState.status, readState.views, syncSessionWorkspaces]);
387
- const viewByWorkspace = useMemo(() => new Map(readState.views.map((view) => [view.workspaceId, view])), [readState.views]);
388
- const sessionOrderInputs = useMemo(() => {
389
- if (readState.status !== 'ready')
390
- return [];
391
- const inputs = [];
392
- for (const workspace of workspaces.items) {
393
- const view = viewByWorkspace.get(workspace.workspaceId);
394
- const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
395
- const bindings = view?.bindings ?? [];
396
- const boundSessionIds = new Set(bindings.map((binding) => binding.sessionId));
397
- const mainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...boundSessionIds]), sessions);
398
- inputs.push({
399
- accountKey: `main:${workspace.workspaceId}`,
400
- sessionIds: mainSessionIds,
401
- updatedAtById: updatedAtById(mainSessionIds, sessions),
402
- });
403
- for (const record of view?.worktrees ?? []) {
404
- const worktreeSessionIds = filterVisibleSessionIds(filterArchivedSessionIds(bindingIdsFor(bindings, record.worktreeId).filter((sessionId) => sessions.ids.includes(sessionId)), archivedSessionIds), sessions);
405
- inputs.push({
406
- accountKey: `worktree:${record.worktreeId}`,
407
- sessionIds: worktreeSessionIds,
408
- updatedAtById: updatedAtById(worktreeSessionIds, sessions),
409
- });
410
- }
411
- }
412
- return inputs;
413
- }, [
414
- archivedSessionIds,
415
- readState.status,
416
- sessions.byId,
417
- sessions.ids,
418
- viewByWorkspace,
419
- workspaces,
420
- workspaces.items,
421
- ]);
422
- const orderedSessionIdsByAccount = useMemo(() => {
423
- const ordered = new Map();
424
- for (const input of sessionOrderInputs) {
425
- const previous = sessionOrderSnapshot.accounts[input.accountKey];
426
- ordered.set(input.accountKey, nextSessionOrderAccount({
427
- baseIds: input.sessionIds,
428
- updatedAtById: input.updatedAtById,
429
- previous,
430
- }).order);
431
- }
432
- return ordered;
433
- }, [sessionOrderInputs, sessionOrderSnapshot]);
434
- useEffect(() => {
435
- if (mode !== 'worktree' || readState.status !== 'ready')
436
- return;
437
- for (const input of sessionOrderInputs) {
438
- sessionOrder.actions.reconcile(input.accountKey, input.sessionIds, input.updatedAtById);
439
- }
440
- sessionOrder.actions.retain(sessionOrderInputs.map((input) => input.accountKey));
441
- }, [mode, readState.status, sessionOrder, sessionOrderInputs]);
442
- const currentSessionLocation = useMemo(() => readState.status === 'ready'
443
- ? resolveCurrentSessionLocation(currentSessionId, workspaces.items, readState.views)
444
- : undefined, [currentSessionId, readState.status, readState.views, workspaces.items]);
445
- const currentRevealKeys = useMemo(() => new Set(currentSessionRevealKeys(currentSessionLocation)), [currentSessionLocation]);
446
- const isCurrentSessionReveal = (key) => currentSessionReveal !== undefined &&
447
- currentSessionReveal.sessionId === currentSessionId &&
448
- currentRevealKeys.has(key) &&
449
- currentSessionReveal.suppressedKeys[key] !== true;
450
- useLayoutEffect(() => {
451
- locateGenerationRef.current += 1;
452
- positionedLocateGenerationRef.current = undefined;
453
- if (mode !== 'worktree') {
454
- setCurrentSessionReveal(undefined);
455
- return;
456
- }
457
- if (searchQueryRef.current.trim().length > 0)
458
- setSearchQuery('');
459
- setCurrentSessionReveal(currentSessionId === undefined
460
- ? undefined
461
- : { sessionId: currentSessionId, suppressedKeys: {} });
462
- }, [currentSessionId, mode]);
463
- useLayoutEffect(() => {
464
- if (mode !== 'worktree' ||
465
- currentSessionId === undefined ||
466
- currentSessionLocation === undefined) {
467
- return;
468
- }
469
- const generation = locateGenerationRef.current;
470
- if (positionedLocateGenerationRef.current === generation)
471
- return;
472
- let cancelled = false;
473
- const frame = requestAnimationFrame(() => {
474
- if (cancelled || generation !== locateGenerationRef.current)
475
- return;
476
- if (!scrollCurrentSessionIntoView(ref.current, currentSessionId))
477
- return;
478
- positionedLocateGenerationRef.current = generation;
479
- });
480
- return () => {
481
- cancelled = true;
482
- cancelAnimationFrame(frame);
483
- };
484
- }, [
485
- currentSessionId,
486
- currentSessionLocation,
487
- currentSessionReveal,
488
- expandSnapshot,
489
- mode,
490
- query,
491
- readState.status,
492
- ]);
493
- useEffect(() => {
494
- if (readState.status !== 'ready' ||
495
- !isCompleteWorktreeWorkspaceSnapshot(workspaceIds, readState.views))
496
- return;
497
- expandState.actions.retain(workspaceIds, readState.views.flatMap((view) => view.worktrees.map((record) => record.worktreeId)));
498
- }, [expandState, readState.status, readState.views, workspaceIds]);
499
- const modalWorkspace = workspaces.items.find((workspace) => workspace.workspaceId === worktreeModalWorkspaceId);
500
- const modalView = worktreeModalWorkspaceId === undefined
501
- ? undefined
502
- : viewByWorkspace.get(worktreeModalWorkspaceId);
503
- const modalReadiness = modalView?.readiness;
504
- const modalSetupStatus = modalView === undefined
505
- ? undefined
506
- : modalReadiness?.status === 'ready'
507
- ? modalView.branches.length === 0
508
- ? 'noLocalBranch'
509
- : undefined
510
- : modalReadiness?.status;
511
- const modalCanCreate = !modalReadLoading && modalSetupStatus === undefined && modalReadiness?.status === 'ready';
512
- useEffect(() => {
513
- if (worktreeModalWorkspaceId === undefined || modalView === undefined)
514
- return;
515
- if (modalView.readiness.status !== 'ready') {
516
- setSelectedBranch('');
517
- setNewBranch('');
518
- return;
519
- }
520
- setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
521
- setNewBranch((current) => {
522
- if (current.length > 0)
523
- return current;
524
- const existingNames = [
525
- ...modalView.branches.map((branch) => branch.name),
526
- ...modalView.worktrees.map((worktree) => worktree.branch),
527
- ];
528
- return createDefaultWorktreeName(existingNames);
529
- });
530
- }, [modalView, worktreeModalWorkspaceId]);
531
- const runMutation = async (operation, refreshOptions) => {
532
- setActionPending(true);
533
- setActionError(undefined);
534
- try {
535
- await operation();
536
- if (refreshOptions !== undefined)
537
- await refresh(refreshOptions);
538
- }
539
- catch (error) {
540
- setActionError(toWorktreeViewError(error));
541
- }
542
- finally {
543
- setActionPending(false);
544
- }
545
- };
546
- const loadImportCandidates = useCallback(async (workspaceId) => {
547
- if (manager === undefined)
548
- return;
549
- setImportCandidates((current) => ({ status: 'loading', candidates: current.candidates }));
550
- await importCandidatesGuard.current.run(() => manager.listImportCandidates({ workspaceId }), (candidates) => {
551
- if (modalWorkspaceIdRef.current !== workspaceId)
552
- return;
553
- setImportCandidates({ status: 'ready', candidates });
554
- }, (error) => {
555
- if (modalWorkspaceIdRef.current !== workspaceId)
556
- return;
557
- setImportCandidates((current) => ({
558
- status: 'error',
559
- candidates: current.candidates,
560
- error: toWorktreeViewError(error),
561
- }));
562
- });
563
- }, [manager]);
564
- const workspaceRenameTrimmed = workspaceRenameDraft.trim();
565
- const workspaceRenameDuplicate = workspaceRenameTarget !== undefined &&
566
- workspaceRenameTrimmed.length > 0 &&
567
- workspaces.items.some((workspace) => workspace.workspaceId !== workspaceRenameTarget.workspaceId &&
568
- workspace.title === workspaceRenameTrimmed);
569
- const workspaceRenameBlocked = workspaceRenamePending ||
570
- workspaceRenameTarget === undefined ||
571
- workspaceRenameTrimmed.length === 0 ||
572
- workspaceRenameTrimmed === workspaceRenameTarget?.currentTitle ||
573
- workspaceRenameDuplicate;
574
- const openWorkspaceRename = (workspace) => {
575
- setWorkspaceRenameTarget({
576
- workspaceId: workspace.workspaceId,
577
- currentTitle: workspace.title,
578
- });
579
- setWorkspaceRenameDraft(workspace.title);
580
- setWorkspaceRenameError(undefined);
581
- };
582
- const closeWorkspaceRename = () => {
583
- if (workspaceRenamePending)
584
- return;
585
- setWorkspaceRenameTarget(undefined);
586
- setWorkspaceRenameError(undefined);
587
- };
588
- const confirmWorkspaceRename = async () => {
589
- const target = workspaceRenameTarget;
590
- if (workspaceRenameBlocked || target === undefined)
591
- return;
592
- if (renameWorkspace === undefined) {
593
- setWorkspaceRenameError({
594
- code: 'WORKSPACE_RENAME_UNAVAILABLE',
595
- message: '',
596
- retryable: true,
597
- });
598
- return;
599
- }
600
- setWorkspaceRenamePending(true);
601
- setWorkspaceRenameError(undefined);
602
- try {
603
- await renameWorkspace(target.workspaceId, workspaceRenameTrimmed);
604
- setWorkspaceRenameTarget(undefined);
605
- }
606
- catch (error) {
607
- setWorkspaceRenameError(toNativeWorktreeViewError(error));
608
- }
609
- finally {
610
- setWorkspaceRenamePending(false);
611
- }
612
- };
613
- const openWorkspaceDelete = (workspace) => {
614
- setWorkspaceDeleteTarget({ workspaceId: workspace.workspaceId, title: workspace.title });
615
- setWorkspaceDeleteError(undefined);
616
- };
617
- const closeWorkspaceDelete = () => {
618
- if (workspaceDeletePending)
619
- return;
620
- setWorkspaceDeleteTarget(undefined);
621
- setWorkspaceDeleteError(undefined);
622
- };
623
- const confirmWorkspaceDelete = async () => {
624
- const target = workspaceDeleteTarget;
625
- if (target === undefined || workspaceDeletePending)
626
- return;
627
- if (deleteWorkspace === undefined) {
628
- setWorkspaceDeleteError({
629
- code: 'WORKSPACE_DELETE_UNAVAILABLE',
630
- message: '',
631
- retryable: true,
632
- });
633
- return;
634
- }
635
- setWorkspaceDeletePending(true);
636
- setWorkspaceDeleteError(undefined);
637
- try {
638
- await deleteWorkspace(target.workspaceId);
639
- setWorkspaceDeleteTarget(undefined);
640
- }
641
- catch (error) {
642
- setWorkspaceDeleteError(toNativeWorktreeViewError(error));
643
- }
644
- finally {
645
- setWorkspaceDeletePending(false);
646
- }
647
- };
648
- const commitWorkspaceDrag = (activeDrag, over) => {
649
- if (workspaceDropCommitted.current)
650
- return;
651
- workspaceDropCommitted.current = true;
652
- setWorkspaceDrag(undefined);
653
- const rows = workspaces.items;
654
- const targetIndex = rows.findIndex((workspace) => workspace.workspaceId === over.workspaceId);
655
- const sourceIndex = rows.findIndex((workspace) => workspace.workspaceId === activeDrag.workspaceId);
656
- if (targetIndex === -1 || sourceIndex === -1)
657
- return;
658
- const beforeWorkspaceId = over.half === 'before' ? over.workspaceId : rows[targetIndex + 1]?.workspaceId;
659
- const anchorIndex = beforeWorkspaceId === undefined
660
- ? rows.length
661
- : rows.findIndex((workspace) => workspace.workspaceId === beforeWorkspaceId);
662
- if (beforeWorkspaceId === activeDrag.workspaceId ||
663
- anchorIndex === sourceIndex ||
664
- anchorIndex === sourceIndex + 1) {
665
- return;
666
- }
667
- if (insertWorkspaceBefore === undefined) {
668
- setActionError({
669
- code: 'WORKSPACE_ORDER_UNAVAILABLE',
670
- message: '',
671
- retryable: true,
672
- });
673
- return;
674
- }
675
- setActionError(undefined);
676
- void insertWorkspaceBefore(activeDrag.workspaceId, beforeWorkspaceId).catch((error) => {
677
- setActionError(toWorktreeViewError(error));
678
- });
679
- };
680
- const commitSessionDrag = (activeDrag, over, sessionIds, workspaceId) => {
681
- if (sessionDropCommitted.current)
682
- return;
683
- sessionDropCommitted.current = true;
684
- setSessionDrag(undefined);
685
- const targetIndex = sessionIds.indexOf(over.sessionId);
686
- const sourceIndex = sessionIds.indexOf(activeDrag.sessionId);
687
- if (targetIndex === -1 || sourceIndex === -1)
688
- return;
689
- const beforeSessionId = over.half === 'before' ? over.sessionId : sessionIds[targetIndex + 1];
690
- const anchorIndex = beforeSessionId === undefined ? sessionIds.length : sessionIds.indexOf(beforeSessionId);
691
- if (beforeSessionId === activeDrag.sessionId ||
692
- anchorIndex === sourceIndex ||
693
- anchorIndex === sourceIndex + 1) {
694
- return;
695
- }
696
- if (insertSessionBefore === undefined) {
697
- setActionError({
698
- code: 'SESSION_ORDER_UNAVAILABLE',
699
- message: '',
700
- retryable: true,
701
- });
702
- return;
703
- }
704
- setActionError(undefined);
705
- const currentOrder = sessionOrderSnapshot.accounts[activeDrag.groupKey]?.order ?? sessionIds;
706
- void insertSessionBefore(workspaceId, activeDrag.sessionId, beforeSessionId)
707
- .then(() => {
708
- sessionOrder.actions.setOrder(activeDrag.groupKey, reorderSessionIds(currentOrder, activeDrag.sessionId, over.sessionId, over.half));
709
- })
710
- .catch((error) => {
711
- setActionError(toWorktreeViewError(error));
712
- });
713
- };
714
- const commitWorktreeDrag = (activeDrag, over, worktreeIds, workspaceId) => {
715
- if (worktreeDropCommitted.current)
716
- return;
717
- worktreeDropCommitted.current = true;
718
- setWorktreeDrag(undefined);
719
- if (activeDrag.workspaceId !== workspaceId)
720
- return;
721
- const move = resolveWorktreeMove(worktreeIds, activeDrag.worktreeId, over.worktreeId, over.half);
722
- if (move === undefined)
723
- return;
724
- if (insertWorktreeBefore === undefined) {
725
- setActionError({
726
- code: 'WORKTREE_ORDER_UNAVAILABLE',
727
- message: '',
728
- retryable: true,
729
- });
730
- return;
731
- }
732
- setActionError(undefined);
733
- void insertWorktreeBefore(workspaceId, activeDrag.worktreeId, move.beforeWorktreeId)
734
- .then(() => refresh({
735
- scope: { kind: 'workspace', workspaceId },
736
- preserveCurrent: true,
737
- invalidateContext: false,
738
- }))
739
- .catch((error) => {
740
- setActionError(toRetryableWorktreeOrderError(error));
741
- });
742
- };
743
- const openSessionRename = (sessionId, currentTitle) => {
744
- setSessionRenameTarget({ sessionId, currentTitle });
745
- setSessionRenameDraft(currentTitle);
746
- setSessionRenameError(undefined);
747
- };
748
- const closeSessionRename = () => {
749
- if (sessionRenamePending)
750
- return;
751
- setSessionRenameTarget(undefined);
752
- setSessionRenameError(undefined);
753
- };
754
- const confirmSessionRename = async () => {
755
- const target = sessionRenameTarget;
756
- const title = sessionRenameDraft.trim();
757
- if (target === undefined || title.length === 0 || sessionRenamePending)
758
- return;
759
- if (renameSession === undefined) {
760
- setSessionRenameError({
761
- code: 'SESSION_RENAME_UNAVAILABLE',
762
- message: '',
763
- retryable: true,
764
- });
765
- return;
766
- }
767
- setSessionRenamePending(true);
768
- setSessionRenameError(undefined);
769
- try {
770
- await renameSession(target.sessionId, title);
771
- setSessionRenameTarget(undefined);
772
- }
773
- catch (error) {
774
- setSessionRenameError(toNativeWorktreeViewError(error));
775
- }
776
- finally {
777
- setSessionRenamePending(false);
778
- }
779
- };
780
- const archiveWorktreeSession = async (sessionId) => {
781
- if (archiveSession === undefined)
782
- return;
783
- await runMutation(() => archiveSession(sessionId));
784
- };
785
- const clearSessionGroups = (groupKeys) => {
786
- if (groupKeys.length === 0)
787
- return;
788
- setExpandedSessionGroups((current) => clearSessionGroupExpansion(current, groupKeys));
789
- };
790
- const suppressCurrentSessionReveal = (key) => {
791
- if (!isCurrentSessionReveal(key))
792
- return false;
793
- setCurrentSessionReveal((current) => {
794
- if (current === undefined || current.sessionId !== currentSessionId)
795
- return current;
796
- return {
797
- ...current,
798
- suppressedKeys: { ...current.suppressedKeys, [key]: true },
799
- };
800
- });
801
- return true;
802
- };
803
- const toggleWorkspace = (workspaceId) => {
804
- const persistedExpanded = isWorkspaceExpanded(expandSnapshot, workspaceId);
805
- const autoExpanded = isCurrentSessionReveal('workspace:' + workspaceId);
806
- const visuallyExpanded = persistedExpanded || autoExpanded;
807
- if (visuallyExpanded && autoExpanded) {
808
- suppressCurrentSessionReveal('workspace:' + workspaceId);
809
- }
810
- if (visuallyExpanded && !persistedExpanded) {
811
- clearSessionGroups([
812
- 'main:' + workspaceId,
813
- ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => 'worktree:' + worktreeId),
814
- ]);
815
- return;
816
- }
817
- expandState.actions.toggleWorkspace(workspaceId);
818
- if (visuallyExpanded) {
819
- clearSessionGroups([
820
- 'main:' + workspaceId,
821
- ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => 'worktree:' + worktreeId),
822
- ]);
823
- }
824
- };
825
- const toggleMain = (workspaceId) => {
826
- const persistedExpanded = isMainExpanded(expandSnapshot, workspaceId);
827
- const autoExpanded = isCurrentSessionReveal('main:' + workspaceId);
828
- const visuallyExpanded = persistedExpanded || autoExpanded;
829
- if (visuallyExpanded && autoExpanded) {
830
- suppressCurrentSessionReveal('main:' + workspaceId);
831
- }
832
- if (visuallyExpanded && !persistedExpanded) {
833
- clearSessionGroups(['main:' + workspaceId]);
834
- return;
835
- }
836
- expandState.actions.toggleMain(workspaceId);
837
- if (visuallyExpanded)
838
- clearSessionGroups(['main:' + workspaceId]);
839
- };
840
- const toggleWorktree = (worktreeId) => {
841
- const persistedExpanded = isWorktreeExpanded(expandSnapshot, worktreeId);
842
- const autoExpanded = isCurrentSessionReveal('worktree:' + worktreeId);
843
- const visuallyExpanded = persistedExpanded || autoExpanded;
844
- if (visuallyExpanded && autoExpanded) {
845
- suppressCurrentSessionReveal('worktree:' + worktreeId);
846
- }
847
- if (visuallyExpanded && !persistedExpanded) {
848
- clearSessionGroups(['worktree:' + worktreeId]);
849
- return;
850
- }
851
- expandState.actions.toggleWorktree(worktreeId);
852
- if (visuallyExpanded)
853
- clearSessionGroups(['worktree:' + worktreeId]);
854
- };
855
- const toggleSessionGroup = (groupKey, autoExpanded) => {
856
- const transientExpanded = expandedSessionGroups[groupKey] === true;
857
- if (autoExpanded) {
858
- suppressCurrentSessionReveal('session-group:' + groupKey);
859
- setExpandedSessionGroups((current) => {
860
- const next = { ...current };
861
- delete next[groupKey];
862
- return next;
863
- });
864
- return;
865
- }
866
- setExpandedSessionGroups((current) => ({
867
- ...current,
868
- [groupKey]: !transientExpanded,
869
- }));
870
- };
871
- const closeWorktreeCreator = (force = false) => {
872
- if (actionPending && !force)
873
- return;
874
- modalReadLoader.current.invalidate();
875
- modalReadViewRef.current = undefined;
876
- importCandidatesGuard.current.invalidate();
877
- setWorktreeModalWorkspaceId(undefined);
878
- setModalReadError(undefined);
879
- setModalReadLoading(false);
880
- };
881
- const openWorktreeCreator = (workspace, defaults = {}) => {
882
- const view = viewByWorkspace.get(workspace.workspaceId);
883
- modalReadLoader.current.invalidate();
884
- modalReadViewRef.current = undefined;
885
- importCandidatesGuard.current.invalidate();
886
- setWorktreeModalWorkspaceId(workspace.workspaceId);
887
- setWorktreeModalMode('create');
888
- setImportCandidates({ status: 'idle', candidates: [] });
889
- setSelectedImportPath(undefined);
890
- setActionError(undefined);
891
- setModalReadError(undefined);
892
- setModalReadLoading(false);
893
- if (view === undefined) {
894
- setSelectedBranch(defaults.baseBranch ?? '');
895
- setNewBranch(defaults.newBranch ?? '');
896
- loadModalWorktreeView(workspace.workspaceId);
897
- return;
898
- }
899
- setSelectedBranch(defaults.baseBranch ?? selectDefaultBaseBranch(view.branches));
900
- setNewBranch(defaults.newBranch ?? createDefaultWorktreeName([
901
- ...view.branches.map((branch) => branch.name),
902
- ...view.worktrees.map((worktree) => worktree.branch),
903
- ]));
904
- };
905
- const changeWorktreeModalMode = (mode) => {
906
- setWorktreeModalMode(mode);
907
- if (mode === 'import' &&
908
- worktreeModalWorkspaceId !== undefined &&
909
- importCandidates.status === 'idle') {
910
- void loadImportCandidates(worktreeModalWorkspaceId);
911
- }
912
- };
913
- const continueWorktreeRegistration = async (registeredWorktree) => {
914
- closeWorktreeCreator(true);
915
- if (createSessionCallback === undefined) {
916
- await refresh({
917
- scope: { kind: 'workspace', workspaceId: registeredWorktree.workspaceId },
918
- preserveCurrent: true,
919
- });
920
- setActionError({
921
- code: 'WORKTREE_REGISTRATION_SESSION_UNAVAILABLE',
922
- message: '',
923
- retryable: true,
924
- });
925
- return;
926
- }
927
- const sessionInput = {
928
- workspaceId: registeredWorktree.workspaceId,
929
- worktreeId: registeredWorktree.worktreeId,
930
- cwd: registeredWorktree.absolutePath,
931
- };
932
- try {
933
- await createSessionCallback(sessionInput);
934
- }
935
- catch (error) {
936
- if (error instanceof WorktreeSessionBindingError && error.retryable) {
937
- setPendingSessionBinding({ ...sessionInput, sessionId: error.sessionId });
938
- }
939
- if (error instanceof WorktreeSessionPermissionError && error.retryable) {
940
- setPendingSessionBinding({
941
- ...sessionInput,
942
- sessionId: error.sessionId,
943
- permissionRequired: true,
944
- });
945
- }
946
- throw error;
947
- }
948
- await refresh({
949
- scope: { kind: 'workspace', workspaceId: registeredWorktree.workspaceId },
950
- preserveCurrent: true,
951
- });
952
- };
953
- const submitWorktree = async () => {
954
- const worktreeName = newBranch.trim();
955
- const selectedImportCandidate = importCandidates.candidates.find((candidate) => candidate.absolutePath === selectedImportPath);
956
- if (manager === undefined || modalWorkspace === undefined)
957
- return;
958
- if (worktreeModalMode === 'create' &&
959
- (!modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0))
960
- return;
961
- if (worktreeModalMode === 'import' && selectedImportCandidate === undefined)
962
- return;
963
- setActionPending(true);
964
- setActionError(undefined);
965
- setPendingSessionBinding(undefined);
966
- try {
967
- const registeredWorktree = worktreeModalMode === 'create'
968
- ? await executeWorktreeAction(manager, {
969
- type: 'createWorktree',
970
- input: {
971
- workspaceId: modalWorkspace.workspaceId,
972
- branch: selectedBranch,
973
- newBranch: worktreeName,
974
- },
975
- })
976
- : await executeWorktreeAction(manager, {
977
- type: 'importWorktree',
978
- input: {
979
- workspaceId: modalWorkspace.workspaceId,
980
- absolutePath: selectedImportCandidate.absolutePath,
981
- },
982
- });
983
- if (registeredWorktree === undefined) {
984
- throw {
985
- code: 'WORKTREE_RECORD_MISSING',
986
- message: '',
987
- retryable: true,
988
- };
989
- }
990
- await continueWorktreeRegistration(registeredWorktree);
991
- }
992
- catch (error) {
993
- setActionError(toWorktreeViewError(error));
994
- }
995
- finally {
996
- setActionPending(false);
997
- }
998
- };
999
- const createSession = async (input) => {
1000
- if (createSessionCallback === undefined) {
1001
- setActionError({
1002
- code: 'SESSION_CREATE_UNAVAILABLE',
1003
- message: '',
1004
- retryable: true,
1005
- });
1006
- return;
1007
- }
1008
- setActionPending(true);
1009
- setActionError(undefined);
1010
- setPendingSessionBinding(undefined);
1011
- try {
1012
- await createSessionCallback(input);
1013
- await refresh({
1014
- scope: { kind: 'workspace', workspaceId: input.workspaceId },
1015
- preserveCurrent: true,
1016
- });
1017
- }
1018
- catch (error) {
1019
- if (error instanceof WorktreeSessionBindingError && error.retryable) {
1020
- setPendingSessionBinding({ ...input, sessionId: error.sessionId });
1021
- }
1022
- if (error instanceof WorktreeSessionPermissionError && error.retryable) {
1023
- setPendingSessionBinding({
1024
- ...input,
1025
- sessionId: error.sessionId,
1026
- permissionRequired: true,
1027
- });
1028
- }
1029
- setActionError(toWorktreeViewError(error));
1030
- }
1031
- finally {
1032
- setActionPending(false);
1033
- }
1034
- };
1035
- const retrySessionBinding = async () => {
1036
- if (manager === undefined || pendingSessionBinding === undefined || pendingSessionArchived)
1037
- return;
1038
- const pending = pendingSessionBinding;
1039
- setActionPending(true);
1040
- setActionError(undefined);
1041
- try {
1042
- await retryWorktreeSessionBinding({
1043
- manager,
1044
- pending,
1045
- archived: false,
1046
- ensureSessionWorkspace: (workspaceId, sessionId) => {
1047
- ensureSessionWorkspace?.(workspaceId, sessionId);
1048
- },
1049
- permission,
1050
- confirmFullAccess,
1051
- onPermissionResult,
1052
- openSession,
1053
- });
1054
- setPendingSessionBinding(undefined);
1055
- await refresh({
1056
- scope: { kind: 'workspace', workspaceId: pending.workspaceId },
1057
- preserveCurrent: true,
1058
- });
1059
- }
1060
- catch (error) {
1061
- if (error instanceof WorktreeSessionBindingError && !error.retryable) {
1062
- setPendingSessionBinding(undefined);
1063
- }
1064
- setActionError(toWorktreeViewError(error));
1065
- }
1066
- finally {
1067
- setActionPending(false);
1068
- }
1069
- };
1070
- const retryForkBinding = async (key) => {
1071
- if (retryForkSession === undefined || forkRetryKey !== undefined)
1072
- return;
1073
- setForkRetryKey(key);
1074
- try {
1075
- await retryForkSession(key);
1076
- }
1077
- catch (error) {
1078
- setActionError(toNativeWorktreeViewError(error));
1079
- }
1080
- finally {
1081
- setForkRetryKey(undefined);
1082
- }
1083
- };
1084
- const openWorkspaceSession = (workspaceId, sessionId) => {
1085
- ensureSessionWorkspace?.(workspaceId, sessionId);
1086
- openWorktreeSession({ open: openSession }, sessionId);
1087
- };
1088
- if (mode !== 'worktree')
43
+ const lifecycle = useLifecycleActions({ read, lifecycleState, source, props, mutation });
44
+ if (source.mode !== 'worktree')
1089
45
  return null;
1090
- const visibleWorkspaces = workspaces.items.filter((workspace) => workspaceMatches(workspace, viewByWorkspace.get(workspace.workspaceId), sessions, query));
46
+ const { ref, width, bounds, collapsed } = source;
47
+ const { t } = props;
1091
48
  return (_jsxs("aside", { ref: ref, className: styles.surface, "data-worktree-surface": true, "data-collapsed": collapsed || undefined, "aria-label": t('mode.navigation'), style: {
1092
49
  width: `${width}px`,
1093
50
  ...(bounds.ready
1094
51
  ? { top: `${bounds.top}px`, height: `${bounds.height}px` }
1095
52
  : { height: '0px', visibility: 'hidden' }),
1096
- }, children: [_jsxs("div", { className: styles.wideContent, children: [_jsxs("header", { className: styles.header, children: [_jsx("span", { className: styles.title, children: t('worktree.title') }), _jsx("button", { type: "button", className: styles.closeButton, "aria-label": t('mode.exit'), onClick: () => {
1097
- actions.setViewMode('workspace-session');
1098
- }, children: _jsx(IconCloseOutline16, {}) })] }), _jsxs("div", { className: styles.searchRow, children: [_jsx("span", { className: styles.searchIcon, "aria-hidden": "true", children: _jsx(IconSearchOutline16, {}) }), _jsx("input", { className: styles.searchInput, "aria-label": t('workspace.search'), placeholder: t('workspace.search'), value: searchQuery, onChange: (event) => {
1099
- setSearchQuery(event.currentTarget.value);
1100
- } }), _jsx("button", { type: "button", className: styles.iconButton, "aria-label": t('workspace.add'), onClick: () => {
1101
- if (createWorkspace !== undefined)
1102
- void runMutation(createWorkspace);
1103
- }, children: _jsx(IconProjectAddOutline16, {}) })] }), _jsxs("div", { className: styles.content, tabIndex: 0, children: [permissionNoticeSnapshot !== undefined && (_jsx("div", { className: styles.notice, role: "status", "data-worktree-permission-notice": true, children: _jsx("p", { className: styles.message, children: formatWorktreePermissionNotice(permissionNoticeSnapshot.result, t) }) })), forkRecoverySnapshot.pending.map((recovery) => {
1104
- const recoveryViewError = forkRecoveryError(recovery);
1105
- return (_jsxs("div", { className: styles.error, role: "alert", "data-fork-recovery": recovery.key, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(recoveryViewError, t) }), _jsxs("div", { className: styles.recoveryActions, children: [retryForkSession !== undefined && recoveryViewError.retryable && (_jsx("button", { type: "button", className: styles.actionButton, disabled: forkRetryKey !== undefined, onClick: () => {
1106
- void retryForkBinding(recovery.key);
1107
- }, children: t('action.retryBinding') })), _jsx("button", { type: "button", className: styles.actionButton, disabled: forkRetryKey !== undefined, onClick: () => {
1108
- openSession(recovery.childSessionId);
1109
- }, children: t('action.openCreatedSession') })] })] }, recovery.key));
1110
- }), actionError !== undefined && (_jsxs("div", { className: styles.error, role: "alert", "data-worktree-error": true, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(actionError, t) }), pendingSessionBinding !== undefined && (_jsxs("div", { className: styles.recoveryActions, children: [_jsx("button", { type: "button", className: styles.actionButton, disabled: actionPending || pendingSessionArchived, onClick: () => {
1111
- void retrySessionBinding();
1112
- }, children: t('action.retryBinding') }), !pendingSessionBinding.permissionRequired && (_jsx("button", { type: "button", className: styles.actionButton, disabled: actionPending, onClick: () => {
1113
- const sessionId = pendingSessionBinding.sessionId;
1114
- setPendingSessionBinding(undefined);
1115
- setActionError(undefined);
1116
- openSession(sessionId);
1117
- }, children: t('action.openCreatedSession') }))] })), actionError.retryable && (_jsx("button", { type: "button", className: styles.retryButton, onClick: () => {
1118
- setActionError(undefined);
1119
- void refresh({ scope: { kind: 'global' } });
1120
- }, children: t('action.retry') }))] })), readState.targetError !== undefined && (_jsxs("div", { className: styles.error, role: "alert", "data-worktree-target-error": true, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(readState.targetError.error, t) }), _jsx("button", { type: "button", className: styles.retryButton, onClick: () => {
1121
- void refresh({
1122
- scope: {
1123
- kind: 'workspaces',
1124
- workspaceIds: readState.targetError.workspaceIds,
1125
- },
1126
- preserveCurrent: true,
1127
- });
1128
- }, children: t('action.retry') })] })), readState.status === 'loading' && (_jsx("p", { className: styles.message, children: t('status.loading') })), readState.status === 'error' && readState.error !== undefined ? (_jsxs("div", { className: styles.error, role: "alert", "data-worktree-error": true, children: [_jsx("p", { className: styles.message, "data-error": "true", children: formatWorktreeViewError(readState.error, t) }), _jsx("button", { type: "button", className: styles.retryButton, onClick: () => {
1129
- void refresh({ scope: { kind: 'global' } });
1130
- }, children: t('action.retry') })] })) : readState.status === 'ready' ? (_jsx("div", { className: styles.workspaceList, children: visibleWorkspaces.length === 0 ? (_jsx("p", { className: styles.empty, children: t('workspace.noMatches') })) : (visibleWorkspaces.map((workspace) => {
1131
- const view = viewByWorkspace.get(workspace.workspaceId);
1132
- const currentBranch = view?.branches.find((branch) => branch.isCurrent)?.name;
1133
- const mainLabel = currentBranch === undefined
1134
- ? t('worktree.main')
1135
- : t('worktree.mainWithBranch', { branch: currentBranch });
1136
- const expanded = isWorkspaceExpanded(expandSnapshot, workspace.workspaceId) ||
1137
- isCurrentSessionReveal('workspace:' + workspace.workspaceId);
1138
- const workspaceMatchesQuery = includesText(workspace.title, query);
1139
- const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
1140
- const workspaceActivitySessionIds = filterVisibleSessionIds(allWorkspaceSessionIds, sessions);
1141
- const workspaceHasOngoingSession = hasOngoingSession(workspaceActivitySessionIds, sessionPresentations);
1142
- const bindings = view?.bindings ?? [];
1143
- const boundSessionIds = new Set(bindings.map((binding) => binding.sessionId));
1144
- const mainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...boundSessionIds]), sessions);
1145
- const mainGroupKey = `main:${workspace.workspaceId}`;
1146
- const orderedMainSessionIds = orderedSessionIdsByAccount.get(mainGroupKey) ?? mainSessionIds;
1147
- const visibleMainSessionIds = mainSessionIds.filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
1148
- const orderedVisibleMainSessionIds = orderedMainSessionIds.filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
1149
- const mainExpanded = isMainExpanded(expandSnapshot, workspace.workspaceId) ||
1150
- isCurrentSessionReveal('main:' + workspace.workspaceId);
1151
- const sessionIds = orderedVisibleMainSessionIds.length === visibleMainSessionIds.length
1152
- ? orderedVisibleMainSessionIds
1153
- : visibleMainSessionIds;
1154
- const mainSessionGroupAutoExpanded = isSessionGroupAutoExpanded(sessionIds, currentSessionId, isCurrentSessionReveal('session-group:' + mainGroupKey));
1155
- const mainSessionGroupExpanded = expandedSessionGroups[mainGroupKey] === true ||
1156
- mainSessionGroupAutoExpanded;
1157
- const worktrees = view?.worktrees ?? [];
1158
- const workspaceWorktreeNames = [
1159
- ...(view?.branches.map((branch) => branch.name) ?? []),
1160
- ...(view?.worktrees.map((worktree) => worktree.branch) ?? []),
1161
- ];
1162
- const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
1163
- return (_jsxs("section", { className: styles.workspaceGroup, "data-workspace-id": workspace.workspaceId, children: [_jsx(WorktreeWorkspaceRow, { t: t, workspace: workspace, expanded: expanded, hasOngoingSession: workspaceHasOngoingSession, actionPending: actionPending, menuOpen: openWorkspaceMenuId === workspace.workspaceId, drag: {
1164
- active: workspaceDrag !== undefined,
1165
- marker: workspaceDrag?.over?.workspaceId === workspace.workspaceId
1166
- ? workspaceDrag.over.half
1167
- : null,
1168
- start: () => {
1169
- workspaceDropCommitted.current = false;
1170
- setWorkspaceDrag({ workspaceId: workspace.workspaceId, over: null });
1171
- },
1172
- hover: (half) => {
1173
- setWorkspaceDrag((current) => current === undefined
1174
- ? current
1175
- : {
1176
- ...current,
1177
- over: { workspaceId: workspace.workspaceId, half },
1178
- });
1179
- },
1180
- drop: (half) => {
1181
- if (workspaceDrag === undefined)
1182
- return;
1183
- commitWorkspaceDrag(workspaceDrag, {
1184
- workspaceId: workspace.workspaceId,
1185
- half,
1186
- });
1187
- },
1188
- end: () => {
1189
- if (workspaceDrag?.over !== null && workspaceDrag?.over !== undefined) {
1190
- commitWorkspaceDrag(workspaceDrag, workspaceDrag.over);
1191
- }
1192
- else {
1193
- setWorkspaceDrag(undefined);
1194
- }
1195
- workspaceDropCommitted.current = false;
1196
- },
1197
- }, onToggle: () => {
1198
- toggleWorkspace(workspace.workspaceId);
1199
- }, onCreateWorktree: () => {
1200
- openWorktreeCreator(workspace);
1201
- }, onRename: () => {
1202
- openWorkspaceRename(workspace);
1203
- }, onDelete: () => {
1204
- openWorkspaceDelete(workspace);
1205
- }, onMenuOpenChange: (open) => {
1206
- setOpenWorkspaceMenuId(open ? workspace.workspaceId : undefined);
1207
- } }), expanded && (_jsxs("div", { className: styles.treeChildren, children: [_jsx(WorktreeGroupRow, { t: t, kind: "main", label: mainLabel, expanded: mainExpanded, hasOngoingSession: hasOngoingSession(mainSessionIds, sessionPresentations), icon: _jsx(IconBranchOutline16, {}), workspaceTitle: workspace.title, onToggle: () => {
1208
- toggleMain(workspace.workspaceId);
1209
- }, menu: {
1210
- open: openMainMenuId === workspace.workspaceId,
1211
- label: mainLabel,
1212
- copyPath: workspace.path,
1213
- showCreate: currentBranch !== undefined,
1214
- showRemove: false,
1215
- disabled: actionPending,
1216
- onOpenChange: (open) => {
1217
- setOpenMainMenuId(open ? workspace.workspaceId : undefined);
1218
- },
1219
- onCreateWorktree: currentBranch === undefined
1220
- ? undefined
1221
- : () => {
1222
- openWorktreeCreator(workspace, {
1223
- baseBranch: currentBranch,
1224
- newBranch: createNumberedWorktreeName(currentBranch, workspaceWorktreeNames),
1225
- });
1226
- },
1227
- }, onCreateSession: createMainSession === undefined
1228
- ? undefined
1229
- : () => {
1230
- createMainSession(workspace.workspaceId);
1231
- } }), mainExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: mainGroupKey, sessionIds: sessionIds, workspaceId: workspace.workspaceId, currentSessionId: currentSessionId, expanded: mainSessionGroupExpanded, actionPending: actionPending, sessions: sessions, sessionPresentations: sessionPresentations, dragState: sessionDrag, onToggleExpanded: () => {
1232
- toggleSessionGroup(mainGroupKey, mainSessionGroupAutoExpanded);
1233
- }, onStartDrag: (groupKey, sessionId) => {
1234
- sessionDropCommitted.current = false;
1235
- setSessionDrag({ groupKey, sessionId, over: null });
1236
- }, onHoverDrag: (sessionId, half) => {
1237
- setSessionDrag((current) => current === undefined
1238
- ? current
1239
- : { ...current, over: { sessionId, half } });
1240
- }, onClearDrag: () => {
1241
- setSessionDrag(undefined);
1242
- }, onFinishDrag: () => {
1243
- sessionDropCommitted.current = false;
1244
- }, onCommitDrag: commitSessionDrag, onOpen: (sessionId) => {
1245
- openWorktreeSession({ open: openSession }, sessionId);
1246
- }, onRename: renameSession === undefined ? undefined : openSessionRename, onFork: forkSession, onArchive: archiveSession === undefined ? undefined : archiveWorktreeSession })), worktrees.length === 0 && (_jsx("p", { className: styles.emptyNested, children: t('worktree.noWorktrees') })), worktrees.map((record) => {
1247
- const worktreeSessionIds = filterVisibleSessionIds(filterArchivedSessionIds(bindingIdsFor(bindings, record.worktreeId).filter((sessionId) => sessions.ids.includes(sessionId)), archivedSessionIds), sessions);
1248
- const worktreeMatchesQuery = workspaceMatchesQuery ||
1249
- includesText(record.branch, query) ||
1250
- includesText(record.absolutePath, query);
1251
- if (query.length > 0 &&
1252
- !worktreeMatchesQuery &&
1253
- !worktreeSessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) {
1254
- return null;
1255
- }
1256
- const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery ||
1257
- sessionMatchesQuery(sessionId, sessions, query));
1258
- const worktreeGroupKey = `worktree:${record.worktreeId}`;
1259
- const orderedWorktreeSessionIds = orderedSessionIdsByAccount.get(worktreeGroupKey) ??
1260
- worktreeSessionIds;
1261
- const orderedVisibleWorktreeSessionIds = orderedWorktreeSessionIds.filter((sessionId) => worktreeMatchesQuery ||
1262
- sessionMatchesQuery(sessionId, sessions, query));
1263
- const sessionIds = orderedVisibleWorktreeSessionIds.length ===
1264
- visibleWorktreeSessionIds.length
1265
- ? orderedVisibleWorktreeSessionIds
1266
- : visibleWorktreeSessionIds;
1267
- const sessionGroupAutoExpanded = isSessionGroupAutoExpanded(sessionIds, currentSessionId, isCurrentSessionReveal('session-group:' + worktreeGroupKey));
1268
- const sessionGroupExpanded = expandedSessionGroups[worktreeGroupKey] === true ||
1269
- sessionGroupAutoExpanded;
1270
- const state = record.status === 'removed'
1271
- ? 'warning'
1272
- : record.health === 'repair' || record.health === 'recovery-needed'
1273
- ? 'error'
1274
- : 'done';
1275
- const stateLabel = record.status === 'removed'
1276
- ? t('worktree.detached')
1277
- : record.health === 'recovery-needed'
1278
- ? t('worktree.recovery')
1279
- : record.health === 'repair'
1280
- ? t('worktree.repair')
1281
- : t('worktree.ready');
1282
- const worktreeExpanded = isWorktreeExpanded(expandSnapshot, record.worktreeId) ||
1283
- isCurrentSessionReveal('worktree:' + record.worktreeId);
1284
- return (_jsxs("div", { className: styles.worktreeGroup, "data-worktree-id": record.worktreeId, children: [_jsx(WorktreeGroupRow, { t: t, kind: "worktree", label: record.branch, worktreeId: record.worktreeId, expanded: worktreeExpanded, hasOngoingSession: hasOngoingSession(worktreeSessionIds, sessionPresentations), icon: _jsx(IconBranchOutline16, {}), workspaceTitle: workspace.title, state: state, stateLabel: stateLabel, onToggle: () => {
1285
- toggleWorktree(record.worktreeId);
1286
- }, onCreateSession: record.status === 'active' && record.health !== 'repair' && record.health !== 'recovery-needed'
1287
- ? () => {
1288
- void createSession({
1289
- workspaceId: record.workspaceId,
1290
- worktreeId: record.worktreeId,
1291
- cwd: record.absolutePath,
1292
- });
1293
- }
1294
- : undefined, menu: {
1295
- open: openWorktreeMenuId === record.worktreeId,
1296
- label: record.branch,
1297
- copyPath: record.absolutePath,
1298
- showCreate: record.status === 'active' && record.health !== 'repair' && record.health !== 'recovery-needed',
1299
- showRemove: record.status === 'active' && record.health !== 'repair' && record.health !== 'recovery-needed',
1300
- disabled: actionPending,
1301
- onOpenChange: (open) => {
1302
- setOpenWorktreeMenuId(open ? record.worktreeId : undefined);
1303
- },
1304
- onCreateWorktree: record.status === 'active' && record.health !== 'repair' && record.health !== 'recovery-needed'
1305
- ? () => {
1306
- openWorktreeCreator(workspace, {
1307
- baseBranch: record.branch,
1308
- newBranch: createNumberedWorktreeName(record.branch, workspaceWorktreeNames),
1309
- });
1310
- }
1311
- : undefined,
1312
- onRemove: record.status === 'active'
1313
- ? () => {
1314
- setWorktreeRemoval(record);
1315
- setActionError(undefined);
1316
- }
1317
- : undefined,
1318
- }, drag: {
1319
- active: sameWorkspaceWorktreeDrag,
1320
- marker: worktreeDrag?.over?.worktreeId === record.worktreeId
1321
- ? worktreeDrag.over.half
1322
- : null,
1323
- start: () => {
1324
- worktreeDropCommitted.current = false;
1325
- setWorktreeDrag({
1326
- workspaceId: workspace.workspaceId,
1327
- worktreeId: record.worktreeId,
1328
- over: null,
1329
- });
1330
- },
1331
- hover: (half) => {
1332
- setWorktreeDrag((current) => current === undefined ||
1333
- current.workspaceId !== workspace.workspaceId
1334
- ? current
1335
- : {
1336
- ...current,
1337
- over: { worktreeId: record.worktreeId, half },
1338
- });
1339
- },
1340
- drop: (half) => {
1341
- if (worktreeDrag === undefined)
1342
- return;
1343
- commitWorktreeDrag(worktreeDrag, { worktreeId: record.worktreeId, half }, worktrees.map((candidate) => candidate.worktreeId), workspace.workspaceId);
1344
- },
1345
- end: () => {
1346
- setWorktreeDrag(undefined);
1347
- worktreeDropCommitted.current = false;
1348
- },
1349
- } }), worktreeExpanded && (_jsx(WorktreeSessionGroup, { t: t, groupKey: worktreeGroupKey, sessionIds: sessionIds, workspaceId: workspace.workspaceId, currentSessionId: currentSessionId, expanded: sessionGroupExpanded, actionPending: actionPending, sessions: sessions, sessionPresentations: sessionPresentations, dragState: sessionDrag, onToggleExpanded: () => {
1350
- toggleSessionGroup(worktreeGroupKey, sessionGroupAutoExpanded);
1351
- }, onStartDrag: (groupKey, sessionId) => {
1352
- sessionDropCommitted.current = false;
1353
- setSessionDrag({ groupKey, sessionId, over: null });
1354
- }, onHoverDrag: (sessionId, half) => {
1355
- setSessionDrag((current) => current === undefined
1356
- ? current
1357
- : { ...current, over: { sessionId, half } });
1358
- }, onClearDrag: () => {
1359
- setSessionDrag(undefined);
1360
- }, onFinishDrag: () => {
1361
- sessionDropCommitted.current = false;
1362
- }, onCommitDrag: commitSessionDrag, onOpen: (sessionId) => {
1363
- openWorkspaceSession(workspace.workspaceId, sessionId);
1364
- }, onRename: renameSession === undefined ? undefined : openSessionRename, onFork: forkSession, onArchive: archiveSession === undefined
1365
- ? undefined
1366
- : archiveWorktreeSession }))] }, record.worktreeId));
1367
- })] }))] }, workspace.workspaceId));
1368
- })) })) : null] })] }), _jsx(WorktreeSessionRenameDialog, { t: t, target: sessionRenameTarget, draft: sessionRenameDraft, pending: sessionRenamePending, error: sessionRenameError, onClose: closeSessionRename, onDraftChange: (draft) => {
1369
- setSessionRenameDraft(draft);
1370
- setSessionRenameError(undefined);
1371
- }, onSubmit: confirmSessionRename }), _jsx(WorktreeWorkspaceRenameDialog, { t: t, target: workspaceRenameTarget, draft: workspaceRenameDraft, pending: workspaceRenamePending, duplicate: workspaceRenameDuplicate, error: workspaceRenameError, onClose: closeWorkspaceRename, onDraftChange: (draft) => {
1372
- setWorkspaceRenameDraft(draft);
1373
- setWorkspaceRenameError(undefined);
1374
- }, onSubmit: confirmWorkspaceRename }), _jsx(WorktreeWorkspaceDeleteDialog, { t: t, target: workspaceDeleteTarget, pending: workspaceDeletePending, error: workspaceDeleteError, onClose: closeWorkspaceDelete, onSubmit: confirmWorkspaceDelete }), _jsx(WorktreeCreateDialog, { t: t, workspace: modalWorkspace, view: modalView, readError: modalReadError, setupStatus: modalSetupStatus, canCreate: modalCanCreate, mode: worktreeModalMode, importCandidates: importCandidates, selectedImportPath: selectedImportPath, selectedBranch: selectedBranch, newBranch: newBranch, actionPending: actionPending, onClose: closeWorktreeCreator, onRetry: () => {
1375
- if (worktreeModalWorkspaceId === undefined)
1376
- return;
1377
- modalReadViewRef.current = undefined;
1378
- setSelectedBranch('');
1379
- setNewBranch('');
1380
- loadModalWorktreeView(worktreeModalWorkspaceId);
1381
- }, onModeChange: changeWorktreeModalMode, onRetryImportCandidates: () => {
1382
- if (worktreeModalWorkspaceId !== undefined) {
1383
- void loadImportCandidates(worktreeModalWorkspaceId);
1384
- }
1385
- }, onSelectedImportPathChange: setSelectedImportPath, onSelectedBranchChange: setSelectedBranch, onNewBranchChange: setNewBranch, onSubmit: submitWorktree }), _jsx(WorktreeRemovalDialog, { t: t, worktree: worktreeRemoval, actionPending: actionPending, onClose: () => {
1386
- setWorktreeRemoval(undefined);
1387
- }, onSubmit: () => {
1388
- if (manager === undefined || worktreeRemoval === undefined)
1389
- return;
1390
- const target = worktreeRemoval;
1391
- const mutationToken = target.mutationToken;
1392
- if (mutationToken === undefined) {
1393
- setActionError({
1394
- code: 'WORKTREE_STATE_CONFLICT',
1395
- message: '',
1396
- retryable: true,
1397
- details: {
1398
- workspaceId: target.workspaceId,
1399
- worktreeId: target.worktreeId,
1400
- },
1401
- });
1402
- return;
1403
- }
1404
- void runMutation(async () => {
1405
- await executeWorktreeAction(manager, {
1406
- type: 'removeWorktree',
1407
- input: {
1408
- workspaceId: target.workspaceId,
1409
- worktreeId: target.worktreeId,
1410
- mutationToken,
1411
- },
1412
- }, permission, onPermissionNotice);
1413
- setWorktreeRemoval(undefined);
1414
- }, {
1415
- scope: { kind: 'workspace', workspaceId: target.workspaceId },
1416
- preserveCurrent: true,
1417
- });
1418
- } }), _jsx(RiskConfirmation, { open: fullAccessConfirmationSnapshot !== undefined, title: t('permission.fullAccessTitle'), description: fullAccessConfirmationSnapshot === undefined
1419
- ? ''
1420
- : t('permission.fullAccessDescription', {
1421
- cwd: fullAccessConfirmationSnapshot.cwd,
1422
- }), acknowledgeLabel: t('permission.fullAccessAcknowledge'), cancelLabel: t('dialog.cancel'), closeLabel: t('dialog.close'), confirmLabel: t('permission.fullAccessEnable'), acknowledged: fullAccessAcknowledged, onAcknowledgedChange: setFullAccessAcknowledged, onCancel: () => {
1423
- setFullAccessAcknowledged(false);
1424
- fullAccessConfirmation?.resolve(false);
1425
- }, onConfirm: () => {
1426
- setFullAccessAcknowledged(false);
1427
- fullAccessConfirmation?.resolve(true);
1428
- } })] }));
53
+ }, children: [_jsxs("div", { className: styles.wideContent, children: [_jsx(SurfaceHeader, { expansion: expansion, props: props, source: source, read: read, mutation: mutation }), _jsx(SurfaceContent, { source: source, props: props, lifecycle: lifecycle, mutation: mutation, session: session, read: read, expansion: expansion, ordering: ordering, drag: drag, menus: menus, registration: registration, native: native, lifecycleState: lifecycleState })] }), _jsx(NativeDialogs, { props: props, native: native }), _jsx(RegistrationDialog, { props: props, registration: registration, registrationState: registrationState, mutation: mutation, read: read }), _jsx(LifecycleDialogs, { props: props, lifecycleState: lifecycleState, mutation: mutation, lifecycle: lifecycle, expansion: expansion, read: read, session: session }), _jsx(AccessConfirmation, { source: source, props: props })] }));
1429
54
  }
1430
55
  //# sourceMappingURL=WorktreeSurface.js.map