|
1 | 1 | <!-- This is a V3 replacement for `FileContextMenu.svelte` --> |
2 | 2 | <script lang="ts"> |
3 | | - import ReduxResult from "$components/shared/ReduxResult.svelte"; |
4 | 3 | import AbsorbPlanModal from "$components/stack/AbsorbPlanModal.svelte"; |
5 | 4 | import DiscardChangesModal from "$components/workspace/DiscardChangesModal.svelte"; |
6 | 5 | import StashIntoBranchModal from "$components/workspace/StashIntoBranchModal.svelte"; |
|
81 | 80 | const clipboardService = inject(CLIPBOARD_SERVICE); |
82 | 81 | const backend = inject(BACKEND); |
83 | 82 | const [, absorbingChanges] = stackService.absorb; |
84 | | - const [splitOffChanges] = stackService.splitBranch; |
85 | | - const [splitBranchIntoDependentBranch] = stackService.splitBranchIntoDependentBranch; |
86 | | -
|
87 | 83 | const projectService = inject(PROJECTS_SERVICE); |
88 | 84 |
|
89 | 85 | const isUncommitted = $derived(selectionId.type === "worktree"); |
90 | | - const isBranchFiles = $derived(selectionId.type === "branch"); |
91 | | - const selectionBranchName = $derived( |
92 | | - selectionId.type === "branch" ? selectionId.branchName : undefined, |
93 | | - ); |
94 | 86 |
|
95 | 87 | // Platform-specific label for "Show in Finder/Explorer/File Manager" |
96 | 88 | const showInFolderLabel = (() => { |
|
165 | 157 | } |
166 | 158 | }); |
167 | 159 | } |
168 | | -
|
169 | | - async function split(changes: TreeChange[]) { |
170 | | - if (!stackId) { |
171 | | - chipToasts.error("No stack selected to split off changes."); |
172 | | - return; |
173 | | - } |
174 | | -
|
175 | | - if (selectionId.type !== "branch") { |
176 | | - chipToasts.error("Please select a branch to split off changes."); |
177 | | - return; |
178 | | - } |
179 | | -
|
180 | | - const branchName = selectionId.branchName; |
181 | | -
|
182 | | - const fileNames = changes.map((change) => change.path); |
183 | | -
|
184 | | - try { |
185 | | - await chipToasts.promise( |
186 | | - (async () => { |
187 | | - const newBranchName = await stackService.fetchNewBranchName(projectId); |
188 | | -
|
189 | | - if (!newBranchName) { |
190 | | - throw new Error("Failed to generate a new branch name."); |
191 | | - } |
192 | | -
|
193 | | - await splitOffChanges({ |
194 | | - projectId, |
195 | | - sourceStackId: stackId, |
196 | | - sourceBranchName: branchName, |
197 | | - fileChangesToSplitOff: fileNames, |
198 | | - newBranchName: newBranchName, |
199 | | - }); |
200 | | - })(), |
201 | | - { |
202 | | - loading: "Splitting off changes", |
203 | | - success: "Changes split off into a new branch", |
204 | | - error: "Failed to split off changes", |
205 | | - }, |
206 | | - ); |
207 | | - } catch (error) { |
208 | | - console.error("Failed to split off changes:", error); |
209 | | - } |
210 | | - } |
211 | | -
|
212 | | - async function splitIntoDependentBranch(changes: TreeChange[]) { |
213 | | - if (!stackId) { |
214 | | - chipToasts.error("No stack selected to split off changes."); |
215 | | - return; |
216 | | - } |
217 | | -
|
218 | | - if (selectionId.type !== "branch") { |
219 | | - chipToasts.error("Please select a branch to split off changes."); |
220 | | - return; |
221 | | - } |
222 | | -
|
223 | | - const branchName = selectionId.branchName; |
224 | | - const fileNames = changes.map((change) => change.path); |
225 | | -
|
226 | | - try { |
227 | | - await chipToasts.promise( |
228 | | - (async () => { |
229 | | - const newBranchName = await stackService.fetchNewBranchName(projectId); |
230 | | -
|
231 | | - if (!newBranchName) { |
232 | | - throw new Error("Failed to generate a new branch name."); |
233 | | - } |
234 | | -
|
235 | | - await splitBranchIntoDependentBranch({ |
236 | | - projectId, |
237 | | - sourceStackId: stackId, |
238 | | - sourceBranchName: branchName, |
239 | | - fileChangesToSplitOff: fileNames, |
240 | | - newBranchName: newBranchName, |
241 | | - }); |
242 | | - })(), |
243 | | - { |
244 | | - loading: "Splitting into dependent branch", |
245 | | - success: "Changes split into a dependent branch", |
246 | | - error: "Failed to split into dependent branch", |
247 | | - }, |
248 | | - ); |
249 | | - } catch (error) { |
250 | | - console.error("Failed to split into dependent branch:", error); |
251 | | - } |
252 | | - } |
253 | 160 | </script> |
254 | 161 |
|
255 | 162 | {#if menuOpen && menuItem} |
|
309 | 216 | onclick={async () => uncommitChanges(stackId, commitId, changes)} |
310 | 217 | /> |
311 | 218 | {/if} |
312 | | - |
313 | | - {#if isBranchFiles && stackId && selectionBranchName} |
314 | | - {@const branchIsConflicted = stackService.isBranchConflicted( |
315 | | - projectId, |
316 | | - stackId, |
317 | | - selectionBranchName, |
318 | | - )} |
319 | | - <ReduxResult {projectId} result={branchIsConflicted?.result}> |
320 | | - {#snippet children(isConflicted)} |
321 | | - {#if isConflicted === false} |
322 | | - <ContextMenuItem |
323 | | - label="Split off changes" |
324 | | - icon="split" |
325 | | - onclick={() => { |
326 | | - menuOpen = false; |
327 | | - split(changes); |
328 | | - }} |
329 | | - /> |
330 | | - <ContextMenuItem |
331 | | - label="Split into dependent branch" |
332 | | - icon="stack-plus" |
333 | | - onclick={() => { |
334 | | - menuOpen = false; |
335 | | - splitIntoDependentBranch(changes); |
336 | | - }} |
337 | | - /> |
338 | | - {/if} |
339 | | - {/snippet} |
340 | | - </ReduxResult> |
341 | | - {/if} |
342 | 219 | </ContextMenuSection> |
343 | 220 | {/if} |
344 | 221 |
|
|
0 commit comments