Skip to content

Commit 12786f0

Browse files
committed
Desktop UI and service for split into dependent branches
- Added menu items and supporting logic for 'Split into dependent branch' in FileContextMenu.svelte. - Added splitBranchIntoDependentBranch support to stackService (API, handler, mutation mapping). This commit covers desktop app changes for the new feature, separate from backend changes.
1 parent 4bb2978 commit 12786f0

File tree

2 files changed

+62
-0
lines changed

2 files changed

+62
-0
lines changed

apps/desktop/src/components/v3/FileContextMenu.svelte

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
const [branchChanges, branchingChanges] = actionService.branchChanges;
6464
const [absorbChanges, absorbingChanges] = actionService.absorb;
6565
const [splitOffChanges] = stackService.splitBranch;
66+
const [splitBranchIntoDependentBranch] = stackService.splitBrancIntoDependentBranch;
6667
6768
const userSettings = getContextStoreBySymbol<Settings, Writable<Settings>>(SETTINGS);
6869
const isUncommitted = $derived(selectionId.type === 'worktree');
@@ -243,6 +244,36 @@
243244
newBranchName: newBranchName.data
244245
});
245246
}
247+
248+
async function splitIntoDependentBranch(changes: TreeChange[]) {
249+
if (!stackId) {
250+
toasts.error('No stack selected to split off changes.');
251+
return;
252+
}
253+
254+
if (selectionId.type !== 'branch') {
255+
toasts.error('Please select a branch to split off changes.');
256+
return;
257+
}
258+
259+
const branchName = selectionId.branchName;
260+
261+
const fileNames = changes.map((change) => change.path);
262+
const newBranchName = await stackService.newBranchName(projectId);
263+
264+
if (!newBranchName.data) {
265+
toasts.error('Failed to generate a new branch name.');
266+
return;
267+
}
268+
269+
await splitBranchIntoDependentBranch({
270+
projectId,
271+
sourceStackId: stackId,
272+
sourceBranchName: branchName,
273+
fileChangesToSplitOff: fileNames,
274+
newBranchName: newBranchName.data
275+
});
276+
}
246277
</script>
247278

248279
<ContextMenu bind:this={contextMenu} rightClickTrigger={trigger}>
@@ -332,6 +363,13 @@
332363
contextMenu.close();
333364
}}
334365
/>
366+
<ContextMenuItem
367+
label="Split into dependent branch"
368+
onclick={async () => {
369+
await splitIntoDependentBranch(changes);
370+
contextMenu.close();
371+
}}
372+
/>
335373
{/if}
336374
{/if}
337375
</ContextMenuSection>

apps/desktop/src/lib/stacks/stackService.svelte.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,10 @@ export class StackService {
808808
return this.api.endpoints.splitBranch.useMutation();
809809
}
810810

811+
get splitBrancIntoDependentBranch() {
812+
return this.api.endpoints.splitBranchIntoDependentBranch.useMutation();
813+
}
814+
811815
stackDetailsUpdateListener(projectId: string) {
812816
return this.api.endpoints.stackDetailsUpdate.useQuery({
813817
projectId
@@ -1538,6 +1542,26 @@ function injectEndpoints(api: ClientState['backendApi']) {
15381542
invalidatesList(ReduxTag.Stacks)
15391543
]
15401544
}),
1545+
splitBranchIntoDependentBranch: build.mutation<
1546+
{ replacedCommits: [string, string][] },
1547+
{
1548+
projectId: string;
1549+
sourceStackId: string;
1550+
sourceBranchName: string;
1551+
newBranchName: string;
1552+
fileChangesToSplitOff: string[];
1553+
}
1554+
>({
1555+
extraOptions: {
1556+
command: 'split_branch_into_dependent_branch'
1557+
},
1558+
query: (args) => args,
1559+
invalidatesTags: (_result, _error, args) => [
1560+
invalidatesItem(ReduxTag.StackDetails, args.sourceStackId),
1561+
invalidatesItem(ReduxTag.BranchChanges, args.sourceStackId),
1562+
invalidatesList(ReduxTag.Stacks)
1563+
]
1564+
}),
15411565
stackDetailsUpdate: build.query<void, { projectId: string }>({
15421566
queryFn: () => ({ data: undefined }),
15431567
async onCacheEntryAdded(arg, lifecycleApi) {

0 commit comments

Comments
 (0)